Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 117 additions & 3 deletions src/browser/base/content/browser-verticaltabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
/**
Expand Down Expand Up @@ -35,6 +76,13 @@ var VerticalTabs = {
return document.getElementById('browser')
},

/**
* @return {HTMLElement?}
*/
get splitter() {
return document.getElementById('verticaltabs-splitter')
},

/**
* @return {Boolean}
*/
Expand All @@ -48,6 +96,8 @@ var VerticalTabs = {
tabBrowserTabs: null,

_initialized: false,
/** @type {MutationObserver?} */
_widthObserver: null,

init() {
if (this._initialized) {
Expand Down Expand Up @@ -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', 'none')
separator.setAttribute('resizeafter', 'sibling')

const tabs = this.tabsToolbar
if (tabs) tabs.parentElement?.insertBefore(separator, tabs)
}
},

disableVerticalTabs() {
Expand All @@ -96,6 +177,39 @@ var VerticalTabs = {
document
.querySelector('#TabsToolbar .toolbar-items')
?.setAttribute('align', 'end')

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()
}

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')
)
}
}
},

/**
Expand Down
43 changes: 31 additions & 12 deletions src/browser/themes/pulse/vertical_tabs.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,40 @@
* 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 {
display: none;
}

#navigator-toolbox-background[verticaltabs='true'] #titlebar {
display: none;
display: none;
}

#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;
}

transition: all 200ms ease-in-out;
#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 {
Expand All @@ -36,9 +55,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 */
Expand Down Expand Up @@ -93,12 +109,15 @@
margin-inline-start: none;
}

#browser #TabsToolbar[collapse='true']:not(:hover) {
max-width: calc(
16px + 2 * var(--inline-tab-padding) + 2 * var(--tab-block-margin)
);
#browser #TabsToolbar[collapse='true'] .tabbrowser-tab {
/* Animate tabs out vertically */
transition: min-height 100ms ease-out, max-height 100ms ease-out;
}

#verticaltabs-splitter {
-moz-box-ordinal-group: 1;
}

:root[sizemode='fullscreen'] #browser #TabsToolbar {
display: none;
}
display: none;
}