tor-browser

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

commit d9af3674fb95c922b2250d9154b1751f9cc0ad54
parent 43b27876fd3256317af43b67ba4622c82aaf752c
Author: Nikki Sharpley <nsharpley@mozilla.com>
Date:   Fri, 28 Nov 2025 20:27:46 +0000

Bug 1932997 - Update vertical tabs closing animations and browser_tabCloseProbes.js r=tabbrowser-reviewers,desktop-theme-reviewers,dao,sclements

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

Diffstat:
Mbrowser/components/sidebar/tests/browser/browser_sidebar_collapsed_close_tab_button.js | 4++++
Mbrowser/components/tabbrowser/content/tabbrowser.js | 10+++++-----
Mbrowser/components/tabbrowser/content/tabs.js | 3++-
Mbrowser/components/tabbrowser/test/browser/tabs/browser.toml | 3---
Mbrowser/components/tabbrowser/test/browser/tabs/browser_tabCloseProbes.js | 50++++++++++++++++++++++++--------------------------
Mbrowser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js | 3+++
Mbrowser/themes/shared/tabbrowser/tabs.css | 15+++++++++++----
7 files changed, 49 insertions(+), 39 deletions(-)

diff --git a/browser/components/sidebar/tests/browser/browser_sidebar_collapsed_close_tab_button.js b/browser/components/sidebar/tests/browser/browser_sidebar_collapsed_close_tab_button.js @@ -4,10 +4,14 @@ "use strict"; add_setup(async () => { + // Force-disable tab animations for tab close + gReduceMotionOverride = true; + await SpecialPowers.pushPrefEnv({ set: [[VERTICAL_TABS_PREF, true]], }); await waitForTabstripOrientation("vertical"); + Assert.equal( Services.prefs.getStringPref(SIDEBAR_VISIBILITY_PREF), "always-show", diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js @@ -5165,7 +5165,6 @@ isLastTab || aTab.pinned || !isVisibleTab || - this.tabContainer.verticalMode || this._removingTabs.size > 3 /* don't want lots of concurrent animations */ || !aTab.hasAttribute( @@ -5190,10 +5189,11 @@ setTimeout( function (tab, tabbrowser) { - if ( - tab.container && - window.getComputedStyle(tab).maxWidth == "0.1px" - ) { + let styles = window.getComputedStyle(tab); + let tabSize = tabbrowser.tabContainer.verticalMode + ? styles.maxHeight + : styles.maxWidth; + if (tab.container && tabSize == "0.1px") { console.assert( false, "Giving up waiting for the tab closing animation to finish (bug 608589)" diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js @@ -411,7 +411,8 @@ * @param {TransitionEvent} event */ on_transitionend(event) { - if (event.propertyName != "max-width") { + let propertyName = this.verticalMode ? "max-height" : "max-width"; + if (event.propertyName != propertyName) { return; } diff --git a/browser/components/tabbrowser/test/browser/tabs/browser.toml b/browser/components/tabbrowser/test/browser/tabs/browser.toml @@ -489,9 +489,6 @@ skip-if = [ "os == 'mac' && os_version == '14.70' && arch == 'x86_64'", # Bug 1932997 "os == 'mac' && os_version == '15.30' && arch == 'aarch64'", # Bug 1932997 ] -fail-if = [ - "vertical_tab", # Bug 1976110, fails in the "vertical-tabs" variant -] ["browser_tabCloseSpacer.js"] skip-if = [ diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_tabCloseProbes.js b/browser/components/tabbrowser/test/browser/tabs/browser_tabCloseProbes.js @@ -58,6 +58,28 @@ function waitForSnapshotCount(histogram, expectedCount) { }, `Collected value should become ${expectedCount}.`); } +/** + * Test close time probe histogram accumulation. + * + * @param animate (Boolean) + * Whether or not the tab is expected to animate on close. + */ +async function testCloseTimeProbe(animate) { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + await BrowserTestUtils.waitForCondition(() => tab._fullyOpen); + + gAnimHistogram.clear(); + gNoAnimHistogram.clear(); + + BrowserTestUtils.removeTab(tab, { animate }); + + await waitForSnapshotCount(gAnimHistogram, animate ? 1 : 0); + assertCount(gNoAnimHistogram.snapshot(), animate ? 0 : 1); + + gAnimHistogram.clear(); + gNoAnimHistogram.clear(); +} + add_setup(async function () { await SpecialPowers.pushPrefEnv({ set: [["test.wait300msAfterTabSwitch", true]], @@ -80,19 +102,7 @@ add_setup(async function () { * close animation. */ add_task(async function test_close_time_anim_probe() { - let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); - await BrowserTestUtils.waitForCondition(() => tab._fullyOpen); - - gAnimHistogram.clear(); - gNoAnimHistogram.clear(); - - BrowserTestUtils.removeTab(tab, { animate: true }); - - await waitForSnapshotCount(gAnimHistogram, 1); - assertCount(gNoAnimHistogram.snapshot(), 0); - - gAnimHistogram.clear(); - gNoAnimHistogram.clear(); + await testCloseTimeProbe(true); }); /** @@ -100,17 +110,5 @@ add_task(async function test_close_time_anim_probe() { * tab close animation. */ add_task(async function test_close_time_no_anim_probe() { - let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); - await BrowserTestUtils.waitForCondition(() => tab._fullyOpen); - - gAnimHistogram.clear(); - gNoAnimHistogram.clear(); - - BrowserTestUtils.removeTab(tab, { animate: false }); - - await waitForSnapshotCount(gNoAnimHistogram, 1); - assertCount(gAnimHistogram.snapshot(), 0); - - gAnimHistogram.clear(); - gNoAnimHistogram.clear(); + await testCloseTimeProbe(false); }); diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js b/browser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js @@ -16,6 +16,9 @@ add_setup(async function () { await SpecialPowers.pushPrefEnv({ set: [["browser.tabs.groups.enabled", true]], }); + + // Force-disable tab animations for tab close + gReduceMotionOverride = true; }); function createManyTabs(number, win = window) { diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css @@ -67,6 +67,8 @@ --tab-selected-outline-color: var(--lwt-tab-line-color, currentColor); } --tab-dragover-transition: transform 200ms var(--animation-easing-function); + --tab-width-transition: min-width 100ms ease-out, max-width 100ms ease-out; + --tab-height-transition: min-height 100ms ease-out, max-height 100ms ease-out; --vertical-tabs-scrollbar-color: auto; @media (-moz-platform: macos) { @@ -145,8 +147,6 @@ padding-bottom: 15px; margin-bottom: -15px; } - - --tab-width-transition: min-width 100ms ease-out, max-width 100ms ease-out; } &[noshadowfortests] { @@ -2170,7 +2170,6 @@ tab-group { } #tabbrowser-tabs[orient="vertical"] { - --tab-min-width: unset; --tab-inline-padding: calc((var(--tab-collapsed-width) - var(--icon-size)) / 2); min-height: 0; @@ -2201,14 +2200,22 @@ tab-group { } .tabbrowser-tab { - flex: none; padding-inline: 0; padding-block: 3px 2px; + /* Set tab height so closing transtion occurs but include padding block values */ + min-height: calc(var(--tab-min-height) + 5px); + max-height: calc(var(--tab-min-height) + 5px); + transition: var(--tab-height-transition); /* prevent the shadow of the close button from being cutoff by the toolbar on the first tab */ &:nth-child(1 of :not([hidden], [pinned])) { padding-block-start: 5px; } + + &:not([pinned], [fadein]) { + max-height: 0.1px; + min-height: 0.1px; + } } .tab-label-container {