diff --git a/README.md b/README.md index 8a29586..0a9ef8e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # titlebar -Emulate OS X window title bar. Extracted from [mafintosh/playback](https://github.com/mafintosh/playback). See the [live demo](http://kapetan.github.io/titlebar/demo/index.html). +Emulate OS X and Windows 10 window title bar. Extracted from [mafintosh/playback](https://github.com/mafintosh/playback). See the [live demo](http://kapetan.github.io/titlebar/demo/index.html). npm install titlebar @@ -31,3 +31,11 @@ The initializer function accepts an options object. - `style` (default `true`): Disable default styling. - `draggable` (default `true`): Disable the [-webkit-app-region](https://developer.chrome.com/apps/app_window) CSS property on the root element. Allows a frameless windows to be dragged in an `electron` application. +- `os` (defaults to current OS, or `mac` if unrecognized): Set the style of title bar to either `mac` or `win`, depending on which OS's title bar you want to mimic. + +# To do + +* Make React compatible +* Add generic title bar (similar to [hyper](http://hyper.is)) to use when no os detected or option given +* Rename the `os` option to `style` +* Slightly rename repo and publish to npm diff --git a/demo/index.html b/demo/index.html index 604e64c..ae236b4 100644 --- a/demo/index.html +++ b/demo/index.html @@ -12,12 +12,20 @@ }; }; - var t = titlebar() + var tm = titlebar({'os':'mac'}) .appendTo(document.body) .on('close', log('close')) .on('minimize', log('minimize')) .on('fullscreen', log('fullscreen')) .on('maximize', log('maximize')); + + document.write('
'); + + var tw = titlebar({'os':'win'}) + .appendTo(document.body) + .on('close', log('close')) + .on('minimize', log('minimize')) + .on('maximize', log('maximize')); - \ No newline at end of file + diff --git a/index.css b/index.css deleted file mode 100644 index 686c704..0000000 --- a/index.css +++ /dev/null @@ -1,116 +0,0 @@ -.titlebar { - padding: 0 3px; - background-color: #f6f6f6; -} - -.titlebar.webkit-draggable { - -webkit-app-region: drag; -} - -.titlebar-stoplight { - float: left; - text-align: left; -} - -.titlebar:after, -.titlebar-stoplight:after { - content: ' '; - display: table; - clear: both; -} - -.titlebar-stoplight:hover svg, -.titlebar-stoplight:hover svg.fullscreen-svg, -.titlebar-stoplight:hover svg.maximize-svg { - opacity: 1; -} - -.titlebar.alt svg.fullscreen-svg { - display: none; -} - -.titlebar.alt svg.maximize-svg { - display: block; -} - -.titlebar-close, -.titlebar-minimize, -.titlebar-fullscreen { - float: left; - width: 10px; - height: 10px; - border-radius: 50%; - margin: 6px 4px; - line-height: 0; -} - -.titlebar.webkit-draggable .titlebar-close, -.titlebar.webkit-draggable .titlebar-minimize, -.titlebar.webkit-draggable .titlebar-fullscreen { - -webkit-app-region: no-drag; -} - -.titlebar-close { - border: 1px solid #e2463f; - background-color: #ff5f57; - margin-left: 6px; -} - -.titlebar-close:active { - border-color: #ad3934; - background-color: #bf4943; -} - -.titlebar-close svg { - width: 6px; - height: 6px; - margin-top: 2px; - margin-left: 2px; - opacity: 0; -} - -.titlebar-minimize { - border: 1px solid #e1a116; - background-color: #ffbd2e; -} - -.titlebar-minimize:active { - border-color: #ad7d15; - background-color: #bf9123; -} - -.titlebar-minimize svg { - width: 8px; - height: 8px; - margin-top: 1px; - margin-left: 1px; - opacity: 0; -} - -.titlebar-fullscreen, -.titlebar-maximize { - border: 1px solid #12ac28; - background-color: #28c940; -} - -.titlebar-fullscreen:active { - border-color: #128622; - background-color: #1f9a31; -} - -.titlebar-fullscreen svg.fullscreen-svg { - width: 6px; - height: 6px; - margin-top: 2px; - margin-left: 2px; - opacity: 0; -} - -.titlebar-fullscreen svg.maximize-svg { - width: 8px; - height: 8px; - margin-top: 1px; - margin-left: 1px; - opacity: 0; - display: none; -} diff --git a/index.js b/index.js index f6c91b3..8619af2 100644 --- a/index.js +++ b/index.js @@ -8,8 +8,10 @@ var $ = require('dombo'); var ALT = 18; var $window = $(window); -var style = fs.readFileSync(__dirname + '/index.css', 'utf-8'); -var html = fs.readFileSync(__dirname + '/index.html', 'utf-8'); +var styleMac = fs.readFileSync(__dirname + '/mac.css', 'utf-8'); +var htmlMac = fs.readFileSync(__dirname + '/mac.html', 'utf-8'); +var styleWin = fs.readFileSync(__dirname + '/win.css', 'utf-8'); +var htmlWin = fs.readFileSync(__dirname + '/win.html', 'utf-8'); var TitleBar = function(options) { if(!(this instanceof TitleBar)) return new TitleBar(options); @@ -17,6 +19,16 @@ var TitleBar = function(options) { events.EventEmitter.call(this); this._options = options || {}; + if (this._options.os !== 'mac' && this._options.os !== 'win'){ + if (process.platform === 'darwin') this._options.os = 'mac'; + else if (process.platform === 'win32') this._options.os = 'win'; + else { + console.warn('No supported OS option was given. Using OS X style as default.') + this._options.os = 'mac'; + } + } + + var html = (this._options.os === 'win') ? htmlWin : htmlMac; var element = domify(html); var $element = $(element); this.element = element; @@ -26,21 +38,32 @@ var TitleBar = function(options) { var self = this; var close = $('.titlebar-close', element)[0]; var minimize = $('.titlebar-minimize', element)[0]; + var maximize = $('.titlebar-maximize', element)[0]; var fullscreen = $('.titlebar-fullscreen', element)[0]; + var os = this._options.os; + $element.on('click', function(e) { var target = e.target; if(close.contains(target)) self.emit('close', e); else if(minimize.contains(target)) self.emit('minimize', e); - else if(fullscreen.contains(target)) { - if(e.altKey) self.emit('maximize', e); - else self.emit('fullscreen', e); + else if (os === 'mac'){ + if(fullscreen.contains(target)) { + if(e.altKey) self.emit('maximize', e); + else self.emit('fullscreen', e); + } + } + else if (os === 'win'){ + if(maximize.contains(target)) { + $element.toggleClass('maximized'); + self.emit('maximize', e); + } } }); $element.on('dblclick', function(e) { var target = e.target; - if(close.contains(target) || minimize.contains(target) || fullscreen.contains(target)) return; + if(close.contains(target) || minimize.contains(target) || (os === 'mac' && fullscreen.contains(target)) || (os === 'win' && maximize.contains(target))) return; self.emit('maximize', e); }); }; @@ -48,6 +71,8 @@ var TitleBar = function(options) { util.inherits(TitleBar, events.EventEmitter); TitleBar.prototype.appendTo = function(target) { + var style = (this._options.os === 'win') ? styleWin : styleMac; + if(typeof target === 'string') target = $(target)[0]; if(this._options.style !== false) defaultcss('titlebar', style); diff --git a/mac.css b/mac.css new file mode 100644 index 0000000..16bc89f --- /dev/null +++ b/mac.css @@ -0,0 +1,121 @@ +.titlebar.tb-mac { + padding: 0 3px; + background-color: #f6f6f6; +} + +.tb-mac.titlebar.webkit-draggable { + -webkit-app-region: drag; +} + +.tb-mac .titlebar-controls { + float: left; + text-align: left; +} + +.tb-mac.titlebar:after, +.tb-mac .titlebar-controls:after { + content: ' '; + display: table; + clear: both; +} + +.tb-mac .titlebar-controls:hover svg, +.tb-mac .titlebar-controls:hover svg.fullscreen-svg, +.tb-mac .titlebar-controls:hover svg.maximize-svg { + opacity: 1; +} + +.tb-mac.titlebar.alt svg.fullscreen-svg { + display: none; +} + +.tb-mac.titlebar.alt svg.maximize-svg { + display: block; +} + +.tb-mac .titlebar-close, +.tb-mac .titlebar-minimize, +.tb-mac .titlebar-fullscreen { + float: left; + width: 10px; + height: 10px; + border-radius: 50%; + margin: 6px 4px; + line-height: 0; +} + +.tb-mac.titlebar.webkit-draggable .titlebar-close, +.tb-mac.titlebar.webkit-draggable .titlebar-minimize, +.tb-mac.titlebar.webkit-draggable .titlebar-fullscreen { + -webkit-app-region: no-drag; +} + +.tb-mac .titlebar-close { + border: 1px solid #e2463f; + background-color: #ff5f57; + margin-left: 6px; +} + +.tb-mac .titlebar-close:active { + border-color: #ad3934; + background-color: #bf4943; +} + +.tb-mac .titlebar-close svg { + width: 6px; + height: 6px; + margin-top: 2px; + margin-left: 2px; + opacity: 0; +} + +.tb-mac .titlebar-minimize { + border: 1px solid #e1a116; + background-color: #ffbd2e; +} + +.tb-mac .titlebar-minimize:active { + border-color: #ad7d15; + background-color: #bf9123; +} + +.tb-mac .titlebar-minimize svg { + width: 8px; + height: 8px; + margin-top: 1px; + margin-left: 1px; + opacity: 0; +} + +.tb-mac .titlebar-fullscreen, +.tb-mac .titlebar-maximize { + border: 1px solid #12ac28; + background-color: #28c940; +} + +.tb-mac .titlebar-fullscreen:active { + border-color: #128622; + background-color: #1f9a31; +} + +.tb-mac .titlebar-fullscreen svg.fullscreen-svg { + width: 6px; + height: 6px; + margin-top: 2px; + margin-left: 2px; + opacity: 0; +} + +.tb-mac .titlebar-fullscreen svg.maximize-svg { + width: 8px; + height: 8px; + margin-top: 1px; + margin-left: 1px; + opacity: 0; + display: none; +} + +.tb-mac.unfocused .titlebar-controls:not(:hover) > * { + background-color: #dcdcdc; + border-color: #d0d0d0; +} diff --git a/index.html b/mac.html similarity index 91% rename from index.html rename to mac.html index 571a022..ee3eb64 100644 --- a/index.html +++ b/mac.html @@ -1,5 +1,5 @@ -
-
+
+
diff --git a/package.json b/package.json index 1d956a1..7852cea 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "titlebar", - "version": "1.4.0", - "description": "Emulate OS X window title bar", + "version": "1.5.0", + "description": "Emulate window title bar", "main": "index.js", "scripts": { - "demo-watch": "wzrd index.js:demo/index.js -- -s titlebar", + "demo-watch": "wzrd index.js:demo/index.js -- -s titlebar", "demo-build": "browserify index.js -o demo/index.js -s titlebar" }, "repository": { diff --git a/win.css b/win.css new file mode 100644 index 0000000..3e2267e --- /dev/null +++ b/win.css @@ -0,0 +1,88 @@ +.titlebar.tb-win { + display: block; + height: 30px; + padding: 0; + background-color: #fff; +} +.titlebar.tb-win.maximized { + height: 22px; +} + +.tb-win.titlebar.webkit-draggable { + -webkit-app-region: drag; +} + +.tb-win .titlebar-controls { + float: right; + text-align: left; +} + +.tb-win.titlebar:after, +.tb-win .titlebar-controls:after { + content: ' '; + display: table; + clear: both; +} + +.tb-win .titlebar-minimize, +.tb-win .titlebar-maximize, +.tb-win .titlebar-close { + float: left; + width: 45px; + height: 29px; + margin: 0 0 1px 1px; + text-align: center; + line-height: 29px; + + -webkit-transition: background-color .2s; + -moz-transition: background-color .2s; + -ms-transition: background-color .2s; + -o-transition: background-color .2s; + transition: background-color .2s; +} +.tb-win.maximized .titlebar-minimize, +.tb-win.maximized .titlebar-maximize, +.tb-win.maximized .titlebar-close { + height: 21px; + line-height: 21px; +} + +.tb-win.titlebar.webkit-draggable .titlebar-minimize, +.tb-win.titlebar.webkit-draggable .titlebar-maximize, +.tb-win.titlebar.webkit-draggable .titlebar-close { + -webkit-app-region: no-drag; +} + +.tb-win .titlebar-minimize svg, +.tb-win .titlebar-maximize svg.maximize-svg, +.tb-win .titlebar-maximize svg.unmaximize-svg, +.tb-win .titlebar-close svg { + width: 10px; + height: 10px; +} +.tb-win .titlebar-close svg polygon { + -webkit-transition: fill .2s; + -moz-transition: fill .2s; + -ms-transition: fill .2s; + -o-transition: fill .2s; + transition: fill .2s; +} + +.tb-win.titlebar:not(.maximized) .titlebar-maximize svg.unmaximize-svg { display: none; } +.tb-win.titlebar.maximized .titlebar-maximize svg.maximize-svg { display: none; } + +.tb-win .titlebar-minimize:hover, +.tb-win .titlebar-maximize:hover, +.tb-win .titlebar-unmaximize:hover { + background-color: #E5E5E5; +} +.tb-win .titlebar-close:hover { + background-color: #E81123; +} +.tb-win .titlebar-close:hover svg polygon { + fill: #fff; +} + +.tb-win.unfocused .titlebar-controls:not(:hover) svg { + opacity: 60%; +} diff --git a/win.html b/win.html new file mode 100644 index 0000000..805231d --- /dev/null +++ b/win.html @@ -0,0 +1,27 @@ +
+
+
+ + + +
+
+ + + + + + + + + + + +
+
+ + + +
+
+