From f880f96501dba2319b5699bd3cceee49973627cc Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Tue, 17 Jan 2023 22:57:24 +1100 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20Allow=20for=20resizing=20vertic?= =?UTF-8?q?al=20tabs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/content/browser-verticaltabs.js | 116 +++++++++++++++++- src/browser/themes/pulse/vertical_tabs.css | 16 +-- 2 files changed, 121 insertions(+), 11 deletions(-) diff --git a/src/browser/base/content/browser-verticaltabs.js b/src/browser/base/content/browser-verticaltabs.js index a9ec5f22..f4585f46 100644 --- a/src/browser/base/content/browser-verticaltabs.js +++ b/src/browser/base/content/browser-verticaltabs.js @@ -5,6 +5,47 @@ const VERTICAL_TABS_POSITION = 'pulse.tabs.vertical' const VERTICAL_TABS_COLLAPSE = 'pulse.tabs.vertical.collapse' +const VERTICAL_TABS_WIDTH = 'pulse.tabs.vertical.width' + +/** + * @param {HTMLElement} toInsertAfter This is the element that I want to insert content after + * @param {HTMLElement} toInsert The element to insert + * + * @throws {Error} If the element you want me to base insertions on has no parent + */ +function insertAfter(toInsertAfter, toInsert) { + const parent = toInsertAfter.parentNode + + if (!parent) { + throw new Error( + 'The element you want me to base insertions on has no parent' + ) + } + + if (toInsertAfter.nextSibling) { + parent.insertBefore(toInsert, toInsertAfter.nextSibling) + } else { + parent.appendChild(toInsert) + } +} + +/** + * Replace a tag with another tag with a different name + * @param {string} tagName The new tag name + * @param {HTMLElement?} initialTag The tag to be changed + */ +function changeXULTagName(tagName, initialTag) { + if (!initialTag) return + if (initialTag.tagName == tagName) return + + const newParent = document.createXULElement(tagName) + + for (const attr of initialTag.attributes) + newParent.setAttribute(attr.name, attr.value) + while (initialTag.firstChild) newParent.appendChild(initialTag.firstChild) + + initialTag.replaceWith(newParent) +} var VerticalTabs = { /** @@ -35,6 +76,13 @@ var VerticalTabs = { return document.getElementById('browser') }, + /** + * @return {HTMLElement?} + */ + get splitter() { + return document.getElementById('verticaltabs-splitter') + }, + /** * @return {Boolean} */ @@ -48,6 +96,8 @@ var VerticalTabs = { tabBrowserTabs: null, _initialized: false, + /** @type {MutationObserver?} */ + _widthObserver: null, init() { if (this._initialized) { @@ -79,9 +129,40 @@ var VerticalTabs = { .querySelector('#TabsToolbar .toolbar-items') ?.setAttribute('align', 'start') - document - .getElementById('TabsToolbar') - ?.setAttribute('collapse', this.browserCollapseTabs ? 'true' : 'false') + this.tabsToolbar?.setAttribute( + 'collapse', + this.browserCollapseTabs ? 'true' : 'false' + ) + this.tabsToolbar?.removeAttribute('flex') + changeXULTagName('vbox', this.tabsToolbar) + + this._widthObserver = new MutationObserver(this._mutationObserverCallback) + if (this.tabsToolbar) + this._widthObserver.observe(this.tabsToolbar, { attributes: true }) + + this.tabsToolbar?.setAttribute( + 'width', + Services.prefs.getIntPref(VERTICAL_TABS_WIDTH, 200) + ) + if (this.tabsToolbar) + this.tabsToolbar.style.width = `${Services.prefs.getIntPref( + VERTICAL_TABS_WIDTH, + 200 + )}px` + + if (!this.splitter) { + const separator = document.createXULElement('splitter') + separator.setAttribute('id', 'verticaltabs-splitter') + separator.setAttribute( + 'class', + 'chromeclass-extrachrome verticaltabs-splitter' + ) + separator.setAttribute('resizebefore', 'sibling') + separator.setAttribute('resizeafter', 'none') + + const tabs = this.tabsToolbar + if (tabs) insertAfter(tabs, separator) + } }, disableVerticalTabs() { @@ -96,6 +177,35 @@ var VerticalTabs = { document .querySelector('#TabsToolbar .toolbar-items') ?.setAttribute('align', 'end') + + changeXULTagName('toolbar', this.tabsToolbar) + this.tabsToolbar?.setAttribute('flex', '1') + + if (this.splitter) { + this.splitter.remove() + } + + if (this._widthObserver) { + this._widthObserver.disconnect() + this._widthObserver = null + } + }, + + /** + * @param {MutationRecord[]} mutationsList + * @param {MutationObserver} _observer + */ + _mutationObserverCallback(mutationsList, _observer) { + for (const mutation of mutationsList) { + if (mutation.type === 'attributes' && mutation.attributeName == 'width') { + const tabsToolbar = document.getElementById('TabsToolbar') + + Services.prefs.setIntPref( + VERTICAL_TABS_WIDTH, + parseInt(tabsToolbar?.getAttribute('width') || '100') + ) + } + } }, /** diff --git a/src/browser/themes/pulse/vertical_tabs.css b/src/browser/themes/pulse/vertical_tabs.css index 46ebf7cc..f8815b00 100644 --- a/src/browser/themes/pulse/vertical_tabs.css +++ b/src/browser/themes/pulse/vertical_tabs.css @@ -10,14 +10,12 @@ } #navigator-toolbox-background[verticaltabs='true'] #titlebar { - display: none; + display: none; } #browser #TabsToolbar { background-color: -moz-Dialog; max-width: 350px; - - transition: all 200ms ease-in-out; } #browser #TabsToolbar:-moz-lwtheme { @@ -36,9 +34,6 @@ /* Stops the tabs from getting squished or stretched */ min-height: unset; max-height: var(--tab-min-height); - - /* Animate tabs out vertically */ - transition: min-height 100ms ease-out, max-height 100ms ease-out; } /* Put the new tab button on the bottom */ @@ -93,6 +88,11 @@ margin-inline-start: none; } +#browser #TabsToolbar[collapse='true'] .tabbrowser-tab { + /* Animate tabs out vertically */ + transition: min-height 100ms ease-out, max-height 100ms ease-out; +} + #browser #TabsToolbar[collapse='true']:not(:hover) { max-width: calc( 16px + 2 * var(--inline-tab-padding) + 2 * var(--tab-block-margin) @@ -100,5 +100,5 @@ } :root[sizemode='fullscreen'] #browser #TabsToolbar { - display: none; -} \ No newline at end of file + display: none; +} From 46a1969085b3a8400a8a0d002178cadc0ce9520d Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Wed, 18 Jan 2023 12:35:54 +1100 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=92=84=20Specify=20a=20min-width=20fo?= =?UTF-8?q?r=20the=20tab=20container?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/browser/themes/pulse/vertical_tabs.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/themes/pulse/vertical_tabs.css b/src/browser/themes/pulse/vertical_tabs.css index f8815b00..30dd7425 100644 --- a/src/browser/themes/pulse/vertical_tabs.css +++ b/src/browser/themes/pulse/vertical_tabs.css @@ -16,6 +16,7 @@ #browser #TabsToolbar { background-color: -moz-Dialog; max-width: 350px; + min-width: 76px; } #browser #TabsToolbar:-moz-lwtheme { From 69f9d255ce07ee5ee41a5ed8d453eaa7eaa2d990 Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Wed, 18 Jan 2023 13:21:34 +1100 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=92=84=20Allow=20resizing=20when=20co?= =?UTF-8?q?llapse=20is=20enabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/content/browser-verticaltabs.js | 6 ++-- src/browser/themes/pulse/vertical_tabs.css | 28 +++++++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/browser/base/content/browser-verticaltabs.js b/src/browser/base/content/browser-verticaltabs.js index f4585f46..e91aa005 100644 --- a/src/browser/base/content/browser-verticaltabs.js +++ b/src/browser/base/content/browser-verticaltabs.js @@ -157,11 +157,11 @@ var VerticalTabs = { 'class', 'chromeclass-extrachrome verticaltabs-splitter' ) - separator.setAttribute('resizebefore', 'sibling') - separator.setAttribute('resizeafter', 'none') + separator.setAttribute('resizebefore', 'none') + separator.setAttribute('resizeafter', 'sibling') const tabs = this.tabsToolbar - if (tabs) insertAfter(tabs, separator) + if (tabs) tabs.parentElement?.insertBefore(separator, tabs) } }, diff --git a/src/browser/themes/pulse/vertical_tabs.css b/src/browser/themes/pulse/vertical_tabs.css index 30dd7425..be08bb7c 100644 --- a/src/browser/themes/pulse/vertical_tabs.css +++ b/src/browser/themes/pulse/vertical_tabs.css @@ -3,6 +3,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +:root { + --vertical-tabs-max-width: 350px; +} + #browser #TabsToolbar .titlebar-spacer, #browser #TabsToolbar .titlebar-buttonbox-container, #browser #TabsToolbar #alltabs-button { @@ -15,10 +19,26 @@ #browser #TabsToolbar { background-color: -moz-Dialog; - max-width: 350px; + max-width: var(--vertical-tabs-max-width); + -moz-box-ordinal-group: 0; +} + +#browser #TabsToolbar:not([collapse='true']) { min-width: 76px; } +#browser #TabsToolbar[collapse='true'] { + max-width: calc( + 16px + 2 * var(--inline-tab-padding) + 2 * var(--tab-block-margin) + ); +} + +/** On collapse hover of tabs or splitter, the max width should increase again */ +#browser #TabsToolbar[collapse='true']:hover, +#verticaltabs-splitter:hover ~ #TabsToolbar[collapse='true'] { + max-width: var(--vertical-tabs-max-width); +} + #browser #TabsToolbar:-moz-lwtheme { background-image: var(--lwt-additional-images); background-repeat: no-repeat, no-repeat, no-repeat; @@ -94,10 +114,8 @@ transition: min-height 100ms ease-out, max-height 100ms ease-out; } -#browser #TabsToolbar[collapse='true']:not(:hover) { - max-width: calc( - 16px + 2 * var(--inline-tab-padding) + 2 * var(--tab-block-margin) - ); +#verticaltabs-splitter { + -moz-box-ordinal-group: 1; } :root[sizemode='fullscreen'] #browser #TabsToolbar { From cfef1575bed052eef7a598d6588e1e2e5efc0b95 Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Wed, 18 Jan 2023 21:00:06 +1100 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=90=9B=20Fix=20tab=20squishing=20when?= =?UTF-8?q?=20reverting=20vertical=20tabs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/browser/base/content/browser-verticaltabs.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/browser/base/content/browser-verticaltabs.js b/src/browser/base/content/browser-verticaltabs.js index e91aa005..501926ed 100644 --- a/src/browser/base/content/browser-verticaltabs.js +++ b/src/browser/base/content/browser-verticaltabs.js @@ -178,8 +178,12 @@ var VerticalTabs = { .querySelector('#TabsToolbar .toolbar-items') ?.setAttribute('align', 'end') - changeXULTagName('toolbar', this.tabsToolbar) - this.tabsToolbar?.setAttribute('flex', '1') + if (this.tabsToolbar) { + changeXULTagName('toolbar', this.tabsToolbar) + this.tabsToolbar.setAttribute('flex', '1') + // Reset the resize value, or else the tabs will end up squished + this.tabsToolbar.style.width = '' + } if (this.splitter) { this.splitter.remove()