commit 7bfb0e0a3a9794ba601e16630eac7d42c3521a18
parent 692649f52101262f67a2f1a36399cc6d4639158e
Author: DJ <dj@walker.dev>
Date: Fri, 24 Oct 2025 14:13:41 +0000
Bug 1987784 - Prevent tabstrip from changing scroll position when expanding a tab group. r=sthompson,tabbrowser-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D264327
Diffstat:
2 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js
@@ -19,6 +19,7 @@
#mustUpdateTabMinHeight = false;
#tabMinHeight = 36;
+ #animatingGroups = new Set();
constructor() {
super();
@@ -34,6 +35,7 @@
this.addEventListener("TabGroupLabelHoverEnd", this);
this.addEventListener("TabGroupExpand", this);
this.addEventListener("TabGroupCollapse", this);
+ this.addEventListener("TabGroupAnimationComplete", this);
this.addEventListener("TabGroupCreate", this);
this.addEventListener("TabGroupRemoved", this);
this.addEventListener("transitionend", this);
@@ -371,13 +373,19 @@
this.previewPanel?.deactivate(event.target.group);
}
- on_TabGroupExpand() {
+ on_TabGroupExpand(event) {
this._invalidateCachedVisibleTabs();
+ this.#animatingGroups.add(event.target.id);
}
- on_TabGroupCollapse() {
+ on_TabGroupCollapse(event) {
this._invalidateCachedVisibleTabs();
this._unlockTabSizing();
+ this.#animatingGroups.add(event.target.id);
+ }
+
+ on_TabGroupAnimationComplete(event) {
+ this.#animatingGroups.delete(event.target.id);
}
on_TabGroupCreate() {
@@ -737,7 +745,10 @@
this.toggleAttribute("overflow", true);
this._updateCloseButtons();
- this._handleTabSelect(true);
+
+ if (!this.#animatingGroups.size) {
+ this._handleTabSelect(true);
+ }
document
.getElementById("tab-preview-panel")
diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js b/browser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js
@@ -239,6 +239,54 @@ add_task(async function test_tabGroupCollapseWhileSelected() {
await removeTabGroup(group);
});
+add_task(async function test_tabGroupPreventScrollOnUncollapse() {
+ let win = await BrowserTestUtils.openNewBrowserWindow();
+
+ // create a tab group that overflows the tabstrip
+ await BrowserTestUtils.overflowTabs(null, win);
+ let bigGroup = win.gBrowser.addTabGroup(win.gBrowser.tabs);
+
+ // create some more tabs after the group
+ createManyTabs(4, win);
+
+ await BrowserTestUtils.waitForCondition(() => {
+ return Array.from(win.gBrowser.tabs).every(tab => tab._fullyOpen);
+ });
+
+ info("selecting the last tab");
+ let tabSelected = BrowserTestUtils.waitForEvent(win, "TabSelect");
+ win.gBrowser.selectedTab = win.gBrowser.tabs[win.gBrowser.tabs.length - 1];
+ await tabSelected;
+
+ info("scrolling to beginning of tabstrip");
+ let arrowScrollbox = win.gBrowser.tabContainer.arrowScrollbox;
+ let scrolledToStart = BrowserTestUtils.waitForCondition(() =>
+ arrowScrollbox.hasAttribute("scrolledtostart")
+ );
+
+ bigGroup.labelElement.scrollIntoView(true);
+ await scrolledToStart;
+ Assert.ok(!bigGroup.collapsed, "Group is expanded");
+ Assert.ok(
+ arrowScrollbox.hasAttribute("scrolledtostart"),
+ "arrowscrollbox is scrolled to start"
+ );
+
+ info("Collapsing and expanding the big group");
+ await TabGroupTestUtils.toggleCollapsed(bigGroup, true);
+ Assert.ok(bigGroup.collapsed, "Group is collapsed");
+ await TabGroupTestUtils.toggleCollapsed(bigGroup, false);
+ Assert.ok(!bigGroup.collapsed, "Group is expanded");
+
+ Assert.ok(
+ arrowScrollbox.hasAttribute("scrolledtostart"),
+ "arrowscrollbox is still scrolled to start"
+ );
+
+ await TabGroupTestUtils.removeTabGroup(bigGroup);
+ BrowserTestUtils.closeWindow(win);
+});
+
/**
* Bug 1979067 - The collapsed tab group's overflow counter should be included in the bounds
* calculations that determine whether the tabstrip scroll button is enabled.