commit e957f391a8f3a623fc3916f4da7974f8578c0632
parent 711947df5d30fd63d1029b1828b2ad4a2854f1d6
Author: Kelly Cochrane <kcochrane@mozilla.com>
Date: Tue, 4 Nov 2025 15:29:44 +0000
Bug 1996103 - Fix issues with collapsing a tab group that contains a split view r=tabbrowser-reviewers,nsharpley,sthompson
Differential Revision: https://phabricator.services.mozilla.com/D270872
Diffstat:
2 files changed, 63 insertions(+), 41 deletions(-)
diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js
@@ -191,13 +191,21 @@
}
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
- if (addedNode.tagName == "tab") {
+ if (gBrowser.isTab(addedNode)) {
this.#updateTabAriaHidden(addedNode);
+ } else if (gBrowser.isSplitViewWrapper(addedNode)) {
+ for (const splitViewTab of addedNode.tabs) {
+ this.#updateTabAriaHidden(splitViewTab);
+ }
}
}
for (const removedNode of mutation.removedNodes) {
- if (removedNode.tagName == "tab") {
+ if (gBrowser.isTab(removedNode)) {
this.#updateTabAriaHidden(removedNode);
+ } else if (gBrowser.isSplitViewWrapper(removedNode)) {
+ for (const splitViewTab of removedNode.tabs) {
+ this.#updateTabAriaHidden(splitViewTab);
+ }
}
}
}
@@ -309,6 +317,7 @@
this.toggleAttribute("collapsed", val);
this.#updateLabelAriaAttributes();
this.#updateTooltip();
+ this.#updateOverflowLabel();
for (const tab of this.tabs) {
this.#updateTabAriaHidden(tab);
}
@@ -390,7 +399,16 @@
* @param {MozTabbrowserTab} tab
*/
#updateTabAriaHidden(tab) {
- if (tab.group?.collapsed && !tab.selected) {
+ if (tab.splitview) {
+ if (
+ tab.group?.collapsed &&
+ !tab.splitview.tabs.some(splitViewTab => splitViewTab.selected)
+ ) {
+ tab.splitview.setAttribute("aria-hidden", "true");
+ } else {
+ tab.splitview.removeAttribute("aria-hidden");
+ }
+ } else if (tab.group?.collapsed && !tab.selected) {
tab.setAttribute("aria-hidden", "true");
} else {
tab.removeAttribute("aria-hidden");
@@ -401,34 +419,31 @@
// When a group containing the active tab is collapsed,
// the overflow count displays the number of additional tabs
// in the group adjacent to the active tab.
- let overflowCountLabel = this.overflowContainer.querySelector(
- ".tab-group-overflow-count"
- );
- let tabs = this.tabs;
- let tabCount = tabs.length;
- const overflowOffset =
- this.hasActiveTab && gBrowser.selectedTab.splitview ? 2 : 1;
-
- if (tabCount > 1) {
- this.toggleAttribute("hasmultipletabs", true);
- } else {
- overflowCountLabel.textContent = "";
- this.toggleAttribute("hasmultipletabs", false);
+ if (this.overflowContainer) {
+ let overflowCountLabel = this.overflowContainer.querySelector(
+ ".tab-group-overflow-count"
+ );
+ let tabs = this.tabs;
+ let tabCount = tabs.length;
+ const overflowOffset =
+ this.hasActiveTab && gBrowser.selectedTab.splitview ? 2 : 1;
+
+ this.toggleAttribute("hasmultipletabs", tabCount > overflowOffset);
+
+ gBrowser.tabLocalization
+ .formatValue("tab-group-overflow-count", {
+ tabCount: tabCount - overflowOffset,
+ })
+ .then(result => (overflowCountLabel.textContent = result));
+ gBrowser.tabLocalization
+ .formatValue("tab-group-overflow-count-tooltip", {
+ tabCount: tabCount - overflowOffset,
+ })
+ .then(result => {
+ overflowCountLabel.setAttribute("tooltiptext", result);
+ overflowCountLabel.setAttribute("aria-description", result);
+ });
}
-
- gBrowser.tabLocalization
- .formatValue("tab-group-overflow-count", {
- tabCount: tabCount - overflowOffset,
- })
- .then(result => (overflowCountLabel.textContent = result));
- gBrowser.tabLocalization
- .formatValue("tab-group-overflow-count-tooltip", {
- tabCount: tabCount - overflowOffset,
- })
- .then(result => {
- overflowCountLabel.setAttribute("tooltiptext", result);
- overflowCountLabel.setAttribute("aria-description", result);
- });
}
#updateLastTabOrSplitViewAttr() {
diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css
@@ -131,6 +131,7 @@
min-height: var(--tabstrip-min-height);
--tab-min-width: 76px;
+ --tab-max-width: 225px;
:root[uidensity="touch"] & .tabbrowser-tab[fadein]:not([pinned]) {
/* Touch mode needs additional space for the close button. */
min-width: max(var(--tab-min-width-pref, var(--tab-min-width)), 86px);
@@ -141,6 +142,8 @@
padding-bottom: 15px;
margin-bottom: -15px;
}
+
+ --tab-width-transition: min-width 100ms ease-out, max-width 100ms ease-out;
}
&[noshadowfortests] {
@@ -204,10 +207,8 @@
&:not([pinned]) {
flex: 100 100;
- max-width: 225px;
- transition:
- min-width 100ms ease-out,
- max-width 100ms ease-out;
+ max-width: var(--tab-max-width);
+ transition: var(--tab-width-transition);
#tabbrowser-tabs[orient="horizontal"] &[fadein] {
min-width: var(--tab-min-width-pref, var(--tab-min-width));
@@ -1157,9 +1158,6 @@
/* Split View */
tab-group > tab-split-view-wrapper {
- &[aria-hidden="true"] {
- display: none;
- }
#tabbrowser-tabs[orient="vertical"] & {
margin-inline-end: var(--space-medium);
@@ -1187,10 +1185,6 @@ tab-group > tab-split-view-wrapper {
.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;
- }
}
&:last-child {
@@ -1210,12 +1204,25 @@ tab-group > tab-split-view-wrapper {
margin-block: var(--tab-block-margin);
margin-inline: 0;
align-items: flex-end;
+ flex: 100 100;
padding: 2px 0;
+ min-width: calc(var(--tab-min-width-pref, var(--tab-min-width)) * 2 + 6px);
+ max-width: var(--tab-max-width);
+ transition: var(--tab-width-transition);
&[last-tab-or-split-view] .tabbrowser-tab:last-child .tab-group-line {
inset-inline-end: calc(var(--tab-border-radius) / 2);
}
+ tab-group[collapsed] &:not([hasactivetab]) {
+ min-width: 0 !important;
+ max-width: 0 !important;
+ max-height: 0 !important;
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ }
+
.tabbrowser-tab {
padding-inline: 2px;
.tab-background {