From cc11203fe9b8af6560a7d386f19d67906d84c8b2 Mon Sep 17 00:00:00 2001 From: Erica Wright Date: Tue, 24 May 2016 13:30:05 -0400 Subject: [PATCH 1/4] allow one-line css (for animations) --- .stylelintrc.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.stylelintrc.json b/.stylelintrc.json index 8b1860c4..50ebf51c 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -7,10 +7,10 @@ "at-rule-name-case": "lower", "at-rule-name-space-after": "always-single-line", "at-rule-semicolon-newline-after": "always", - "block-closing-brace-newline-after": "always", - "block-closing-brace-newline-before": "always", + "block-closing-brace-newline-after": "always-multi-line", + "block-closing-brace-newline-before": "always-multi-line", "block-no-empty": true, - "block-opening-brace-newline-after": "always", + "block-opening-brace-newline-after": "always-multi-line", "block-opening-brace-space-before": "always", "color-hex-case": "lower", "color-hex-length": "short", @@ -61,9 +61,8 @@ "margin-bottom", "margin-left" ]}], { "unspecified": "bottomAlphabetical" }], - "declaration-block-semicolon-newline-after": "always", + "declaration-block-semicolon-newline-after": "always-multi-line", "declaration-block-semicolon-space-before": "never", - "declaration-block-single-line-max-declarations": 1, "declaration-block-trailing-semicolon": "always", "declaration-colon-newline-after": "always-multi-line", "declaration-colon-space-before": "never", From b108ea8b40b2ff961cc5c3a77ac20b2ba5ef142d Mon Sep 17 00:00:00 2001 From: Erica Wright Date: Tue, 24 May 2016 13:36:19 -0400 Subject: [PATCH 2/4] animate fade and slide in tabs, no slide in on tabs that appear at the bottom --- skin/light/light.css | 41 ++++++++++++++++++++++++++++++++++++++--- verticaltabs.jsm | 21 +++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/skin/light/light.css b/skin/light/light.css index 221e6883..1e388a0a 100644 --- a/skin/light/light.css +++ b/skin/light/light.css @@ -164,9 +164,6 @@ .tabbrowser-tab { width: 260px !important; - height: 36px !important; - min-height: 36px !important; - max-height: 36px !important; margin: 0 !important; border: 0 !important; border-left: 4px solid transparent !important; @@ -178,6 +175,44 @@ color: #333 !important; } +.tabbrowser-tab.only-fade-in { + min-height: 36px; + max-height: 36px; + animation: 0.5s fade-in; + animation-fill-mode: forwards; +} + +.tabbrowser-tab.tab-hidden { + min-height:36px; + animation: 0.5s fade-out, 0.5s 0.5s slide-out; + animation-fill-mode: forwards; +} + +.tabbrowser-tab.tab-visible { + animation: 0.5s slide-in, 0.5s 0.5s fade-in; + animation-fill-mode: forwards; +} + +@keyframes fade-out { + 0% { opacity: 1; } + 100% { opacity: 0; } +} + +@keyframes slide-out { + 0% { max-height: 36px; min-height: 36px; opacity: 0; } + 100% { max-height: 0; min-height: 0; opacity: 0; } +} + +@keyframes fade-in { + 0% { opacity: 0; } + 100% { opacity: 1; } +} + +@keyframes slide-in { + 0% { max-height: 0; min-height: 0; opacity: 0; } + 100% { max-height: 36px; min-height: 36px; opacity: 0; } +} + .tabbrowser-tab[selected="true"], .tabbrowser-tab[multiselect="true"] { margin: 0 !important; diff --git a/verticaltabs.jsm b/verticaltabs.jsm index d2befa20..9843e08d 100644 --- a/verticaltabs.jsm +++ b/verticaltabs.jsm @@ -109,6 +109,7 @@ VerticalTabs.prototype = { }.bind(this); this.window.VerticalTabs = this; + this.removeTab = this.window.gBrowser.removeTab.bind(this.window.gBrowser); this.inferFromText = this.window.ToolbarIconColor.inferFromText; let AppConstants = this.AppConstants; let window = this.window; @@ -148,6 +149,7 @@ VerticalTabs.prototype = { }.bind(this.window.ToolbarIconColor); this.unloaders.push(function () { this.window.ToolbarIconColor.inferFromText = this.inferFromText; + this.window.gBrowser.removeTab = this.removeTab; this.window.BrowserOpenTab = this.BrowserOpenTab; delete this.window.VerticalTabs; }); @@ -420,6 +422,25 @@ VerticalTabs.prototype = { } else { aTab.setAttribute('crop', 'end'); } + aTab.classList.remove('tab-hidden'); + if (aTab.attributes['last-tab'] === true) { + aTab.classList.add('only-fade-in'); + }else { + aTab.classList.add('tab-visible'); + } + + this.window.gBrowser.removeTab = (aTab) => { + aTab.classList.remove('tab-visible', 'only-fade-in'); + aTab.classList.add('tab-hidden'); + aTab.addEventListener('animationend', (e) => { + if (e.animationName === 'fade-out') { + let tabStack = this.document.getAnonymousElementByAttribute(aTab, 'class', 'tab-stack'); + tabStack.collapsed = true; //there is a visual jump if we do not collapse the tab before the end of the animation + } else if (e.animationName === 'slide-out') { + this.removeTab(aTab); + } + }); + }; }, unload: function () { From fa6b3eacfe088943b558472ce9b4b519f032bece Mon Sep 17 00:00:00 2001 From: Erica Wright Date: Tue, 24 May 2016 16:20:48 -0400 Subject: [PATCH 3/4] move bind to when removeTab was called, clean styles --- skin/light/light.css | 30 +++++++++++------------------- verticaltabs.jsm | 16 +++++++--------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/skin/light/light.css b/skin/light/light.css index 1e388a0a..9215891f 100644 --- a/skin/light/light.css +++ b/skin/light/light.css @@ -1,5 +1,9 @@ @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); +:root { + --tab-animation-time: 0.5s; +} + #main-window[privatebrowsingmode="temporary"] #titlebar-buttonbox-container { margin-top: 4px; } @@ -164,6 +168,8 @@ .tabbrowser-tab { width: 260px !important; + max-height: 36px; + min-height: 36px; margin: 0 !important; border: 0 !important; border-left: 4px solid transparent !important; @@ -175,22 +181,12 @@ color: #333 !important; } -.tabbrowser-tab.only-fade-in { - min-height: 36px; - max-height: 36px; - animation: 0.5s fade-in; - animation-fill-mode: forwards; -} - .tabbrowser-tab.tab-hidden { - min-height:36px; - animation: 0.5s fade-out, 0.5s 0.5s slide-out; - animation-fill-mode: forwards; + animation: var(--tab-animation-time) fade-out, var(--tab-animation-time) var(--tab-animation-time) slide-out; } .tabbrowser-tab.tab-visible { - animation: 0.5s slide-in, 0.5s 0.5s fade-in; - animation-fill-mode: forwards; + animation: 1s slide-fade-in; } @keyframes fade-out { @@ -203,14 +199,10 @@ 100% { max-height: 0; min-height: 0; opacity: 0; } } -@keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@keyframes slide-in { +@keyframes slide-fade-in { 0% { max-height: 0; min-height: 0; opacity: 0; } - 100% { max-height: 36px; min-height: 36px; opacity: 0; } + 50% { max-height: 36px; min-height: 36px; opacity: 0; } + 100% { max-height: 36px; min-height: 36px; opacity: 1; } } .tabbrowser-tab[selected="true"], diff --git a/verticaltabs.jsm b/verticaltabs.jsm index 9843e08d..94d1525f 100644 --- a/verticaltabs.jsm +++ b/verticaltabs.jsm @@ -109,7 +109,7 @@ VerticalTabs.prototype = { }.bind(this); this.window.VerticalTabs = this; - this.removeTab = this.window.gBrowser.removeTab.bind(this.window.gBrowser); + this.removeTab = this.window.gBrowser.removeTab; this.inferFromText = this.window.ToolbarIconColor.inferFromText; let AppConstants = this.AppConstants; let window = this.window; @@ -417,27 +417,25 @@ VerticalTabs.prototype = { if (this.pushToTop) { this.window.gBrowser.moveTabTo(aTab, 0); } + + aTab.classList.add('tab-visible'); + aTab.classList.remove('tab-hidden'); + if (this.document.getElementById('main-window').getAttribute('tabspinned') !== 'true') { aTab.removeAttribute('crop'); } else { aTab.setAttribute('crop', 'end'); } - aTab.classList.remove('tab-hidden'); - if (aTab.attributes['last-tab'] === true) { - aTab.classList.add('only-fade-in'); - }else { - aTab.classList.add('tab-visible'); - } this.window.gBrowser.removeTab = (aTab) => { - aTab.classList.remove('tab-visible', 'only-fade-in'); + aTab.classList.remove('tab-visible'); aTab.classList.add('tab-hidden'); aTab.addEventListener('animationend', (e) => { if (e.animationName === 'fade-out') { let tabStack = this.document.getAnonymousElementByAttribute(aTab, 'class', 'tab-stack'); tabStack.collapsed = true; //there is a visual jump if we do not collapse the tab before the end of the animation } else if (e.animationName === 'slide-out') { - this.removeTab(aTab); + this.removeTab.bind(this.window.gBrowser)(aTab); } }); }; From 29d6003227db1fadaabb1bdb2c0e58ffebbb51ba Mon Sep 17 00:00:00 2001 From: Erica Wright Date: Fri, 27 May 2016 09:57:30 -0400 Subject: [PATCH 4/4] cut animation down to 150ms --- skin/light/light.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skin/light/light.css b/skin/light/light.css index 9215891f..29a5cdf6 100644 --- a/skin/light/light.css +++ b/skin/light/light.css @@ -1,7 +1,7 @@ @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); :root { - --tab-animation-time: 0.5s; + --tab-animation-time: 150ms; } #main-window[privatebrowsingmode="temporary"] #titlebar-buttonbox-container { @@ -186,7 +186,7 @@ } .tabbrowser-tab.tab-visible { - animation: 1s slide-fade-in; + animation: 300ms slide-fade-in; } @keyframes fade-out {