tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 5a36124942f4affb61b7394e62d6461cf5d260fd
parent f35f40300ec3a0a8faa1f34ceddfcf5f6394820c
Author: Kelly Cochrane <kcochrane@mozilla.com>
Date:   Thu, 30 Oct 2025 13:23:40 +0000

Bug 1992844 - Update styles for split views within tab groups r=tabbrowser-reviewers,sthompson

Differential Revision: https://phabricator.services.mozilla.com/D269229

Diffstat:
Mbrowser/components/tabbrowser/content/tabbrowser.js | 39++++++++++++++++++++++++++++++++++-----
Mbrowser/components/tabbrowser/content/tabgroup.js | 17+++++++++++++++++
Mbrowser/themes/shared/tabbrowser/tabs.css | 81++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
3 files changed, 119 insertions(+), 18 deletions(-)

diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js @@ -6331,6 +6331,15 @@ return !!element?.classList?.contains("tab-group-label"); } + /** + * @param {Element} element + * @returns {boolean} + * `true` if element is a `<tab-split-view-wrapper>` + */ + isSplitViewWrapper(element) { + return !!(element?.tagName == "tab-split-view-wrapper"); + } + _updateTabsAfterInsert() { for (let i = 0; i < this.tabs.length; i++) { this.tabs[i]._tPos = i; @@ -6607,10 +6616,26 @@ if (aTab.group && aTab.group.id === aGroup.id) { return; } - - this.#handleTabMove(aTab, () => aGroup.appendChild(aTab), metricsContext); - this.removeFromMultiSelectedTabs(aTab); - this.tabContainer._notifyBackgroundTab(aTab); + if (aTab.splitview) { + let splitViewTabs = aTab.splitview.tabs; + this.#handleTabMove( + aTab.splitview, + () => aGroup.appendChild(aTab.splitview), + metricsContext + ); + for (const splitViewTab of splitViewTabs) { + this.removeFromMultiSelectedTabs(splitViewTab); + this.tabContainer._notifyBackgroundTab(splitViewTab); + } + } else { + this.#handleTabMove( + aTab, + () => aGroup.appendChild(aTab), + metricsContext + ); + this.removeFromMultiSelectedTabs(aTab); + this.tabContainer._notifyBackgroundTab(aTab); + } } /** @@ -6685,8 +6710,12 @@ tabs = [element]; } else if (this.isTabGroup(element)) { tabs = element.tabs; + } else if (this.isSplitViewWrapper(element)) { + tabs = element.tabs; } else { - throw new Error("Can only move a tab or tab group within the tab bar"); + throw new Error( + "Can only move a tab, tab group, or split view within the tab bar" + ); } let wasFocused = document.activeElement == this.selectedTab; diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js @@ -187,6 +187,7 @@ }); this.hasActiveTab = hasActiveTab; this.#updateOverflowLabel(); + this.#updateLastTabOrSplitViewAttr(); } for (const mutation of mutations) { for (const addedNode of mutation.addedNodes) { @@ -430,6 +431,22 @@ }); } + #updateLastTabOrSplitViewAttr() { + const LAST_ITEM_ATTRIBUTE = "last-tab-or-split-view"; + let lastTab = this.tabs[this.tabs.length - 1]; + let currentLastTabOrSplitView = lastTab.splitview + ? lastTab.splitview + : lastTab; + + let prevLastTabOrSplitView = this.querySelector( + `[${LAST_ITEM_ATTRIBUTE}]` + ); + if (prevLastTabOrSplitView !== currentLastTabOrSplitView) { + prevLastTabOrSplitView?.toggleAttribute(LAST_ITEM_ATTRIBUTE); + currentLastTabOrSplitView.toggleAttribute(LAST_ITEM_ATTRIBUTE); + } + } + /** * @returns {MozTabbrowserTab[]} */ diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css @@ -1157,32 +1157,79 @@ /* Split View */ tab-group > tab-split-view-wrapper { + &[aria-hidden="true"] { + display: none; + } #tabbrowser-tabs[orient="vertical"] & { - margin-block: calc(var(--space-xsmall) * -1); + margin-inline-end: var(--space-medium); + + #tabbrowser-tabs[expanded] & { + margin-inline-start: calc(var(--space-medium) + var(--tab-inner-inline-margin) - var(--space-xsmall)); + } - .tabbrowser-tab:last-child { + #tabbrowser:not([expanded]) & { + margin-inline-start: calc(var(--space-medium) - var(--space-xsmall)); + } + + #tabbrowser-tabs:not([expanded]) & { .tab-group-line { - display: none; + inset-inline-start: calc(((var(--space-medium)) * -1) + 2px) !important; } } - } - @container vertical-tabs-container (max-width: 210px) { - #tabbrowser-tabs[orient="vertical"] & { - margin-inline-start: 0; + &[last-tab-or-split-view] > .tabbrowser-tab .tab-group-line { + inset-block-start: calc(var(--space-xsmall) * -2); + } + + > .tabbrowser-tab { + overflow: visible; + + .tab-group-line { + inset-inline-start: calc(var(--space-medium) * -1) !important; + inset-block: calc(var(--space-xsmall) * -1); + + @container vertical-tabs-container (max-width: 210px) { + inset-inline-start: calc(var(--space-large) * -1) !important; + } + } - .tabbrowser-tab:last-child { + &:last-child { .tab-group-line { - display: flex; + display: none; + + @container vertical-tabs-container (max-width: 210px) { + display: flex; + } } } } } +} + +#tabbrowser-tabs[orient="horizontal"] tab-split-view-wrapper { + margin-block: var(--tab-block-margin); + margin-inline: 0; + align-items: flex-end; + padding: 2px 0; + + &[last-tab-or-split-view] .tabbrowser-tab:last-child .tab-group-line { + inset-inline-end: calc(var(--tab-border-radius) / 2); + } - #tabbrowser-tabs[orient="horizontal"] & { - margin-inline: 0; - padding-block-end: 0; - padding-inline: 0; + .tabbrowser-tab { + padding-inline: 2px; + .tab-background { + --tab-min-height: 32px; + + .tab-group-line { + inset-block-end: calc(((var(--tab-block-margin) / 2) + var(--space-xsmall)) * -1); + inset-inline-start: calc(var(--space-small) * -2); + } + } + + tab-group & { + overflow: visible; + } } } @@ -1263,6 +1310,7 @@ tab-group > tab-split-view-wrapper { #tabbrowser-tabs[orient="vertical"] & { border-radius: var(--tab-border-radius); gap: var(--space-xsmall); + grid-template-columns: 49.5% 49.5%; @container vertical-tabs-container (max-width: 210px) { grid-template-columns: 1fr; @@ -1279,6 +1327,13 @@ tab-group > tab-split-view-wrapper { } } } + + #tabbrowser-tabs[orient="vertical"]:not([expanded]) & { + .tab-close-button { + top: -5px; + inset-inline-start: -7px; + } + } } /* Tab Groups */