tor-browser

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

commit dde1edbe3c28e2b6df02092ebb10362603e4dccf
parent 3fc985a858eb49c1e51f4b1ee763af52ca94f70e
Author: Jonathan Sudiaman <jsudiaman@mozilla.com>
Date:   Wed,  7 Jan 2026 15:00:15 +0000

Bug 1997132 - Add positioning information to ARIA labels for tabs in a split view. r=tabbrowser-reviewers,fluent-reviewers,sthompson,bolsson

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

Diffstat:
Mbrowser/components/tabbrowser/content/tab.js | 40++++++++++++++++++++++++++++++----------
Mbrowser/components/tabbrowser/content/tabsplitview.js | 1+
Mbrowser/components/tabbrowser/test/browser/tabs/browser_tab_splitview.js | 26++++++++++++++++++++++++++
Mbrowser/locales/en-US/browser/tabbrowser.ftl | 14++++++++++++--
4 files changed, 69 insertions(+), 12 deletions(-)

diff --git a/browser/components/tabbrowser/content/tab.js b/browser/components/tabbrowser/content/tab.js @@ -791,20 +791,11 @@ #updateOnTabSplit() { if (this.splitview) { this.setAttribute("aria-level", 2); - - // Add "Split view" to label if tab is within a split view - let splitViewLabel = gBrowser.tabLocalization.formatValueSync( - "tabbrowser-tab-label-tab-split-view" - ); - this.setAttribute( - "aria-label", - `${this.getAttribute("label")}, ${splitViewLabel}` - ); } } #updateOnTabUnsplit() { - if (this.splitview) { + if (!this.splitview) { this.setAttribute("aria-level", 1); // `posinset` and `setsize` only need to be set explicitly // on split view tabs so that a11y tools can tell users that a @@ -814,6 +805,35 @@ this.removeAttribute("aria-label"); } } + + /** + * Set `aria-label` for this tab to indicate that it's in a Split View, + * along with its position within the Split View. + * + * @param {number} index + * The index of this tab in the Split View. + */ + updateSplitViewAriaLabel(index) { + let l10nId = ""; + switch (index) { + case 0: + l10nId = window.RTL_UI + ? "tabbrowser-tab-label-tab-split-view-right" + : "tabbrowser-tab-label-tab-split-view-left"; + break; + case 1: + l10nId = window.RTL_UI + ? "tabbrowser-tab-label-tab-split-view-left" + : "tabbrowser-tab-label-tab-split-view-right"; + break; + } + if (l10nId) { + const ariaLabel = gBrowser.tabLocalization.formatValueSync(l10nId, { + label: this.getAttribute("label"), + }); + this.setAttribute("aria-label", ariaLabel); + } + } } customElements.define("tabbrowser-tab", MozTabbrowserTab, { diff --git a/browser/components/tabbrowser/content/tabsplitview.js b/browser/components/tabbrowser/content/tabsplitview.js @@ -115,6 +115,7 @@ // tab is "1 of 2" in the split view, for example. tab.setAttribute("aria-posinset", index + 1); tab.setAttribute("aria-setsize", this.tabs.length); + tab.updateSplitViewAriaLabel(index); }); } else { this.remove(); diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_tab_splitview.js b/browser/components/tabbrowser/test/browser/tabs/browser_tab_splitview.js @@ -80,6 +80,24 @@ add_task(async function test_splitViewCreateAndAddTabs() { "The split view wrapper has the expected attribute when it does not contain the selected tab" ); + // Verify ARIA labels for split view tabs + const splitViewLeft = gBrowser.tabLocalization.formatValueSync( + "tabbrowser-tab-label-tab-split-view-left", + { label: "" } + ); + const splitViewRight = gBrowser.tabLocalization.formatValueSync( + "tabbrowser-tab-label-tab-split-view-right", + { label: "" } + ); + Assert.ok( + tab1.getAttribute("aria-label").includes(splitViewLeft), + "Left tab has the correct ARIA label." + ); + Assert.ok( + tab2.getAttribute("aria-label").includes(splitViewRight), + "Right tab has the correct ARIA label." + ); + gBrowser.selectTabAtIndex(tab1._tPos); await BrowserTestUtils.waitForMutationCondition( splitview, @@ -103,6 +121,14 @@ add_task(async function test_splitViewCreateAndAddTabs() { 1, "Tabs have been unsplit from split view" ); + Assert.ok( + !tab1.hasAttribute("aria-label"), + "ARIA label was removed from the left tab." + ); + Assert.ok( + !tab2.hasAttribute("aria-label"), + "ARIA label was removed from the right tab." + ); let tab3Panel = tab3.linkedBrowser.closest(".browserSidebarContainer"); let tab4Panel = tab4.linkedBrowser.closest(".browserSidebarContainer"); diff --git a/browser/locales/en-US/browser/tabbrowser.ftl b/browser/locales/en-US/browser/tabbrowser.ftl @@ -419,8 +419,18 @@ tab-note-editor-character-limit = ## Split View # Split view tabs display their respective contents side by side -# Displayed within the tooltip on tabs inside of a tab split view -tabbrowser-tab-label-tab-split-view = Split view +# Displayed within the tooltip on the left tab inside of a tab split view +# "left" corresponds to the visual position. Translate literally; do not swap for RTL languages. +# Variables: +# $label (String): the text label of the tab visible in the tab strip +tabbrowser-tab-label-tab-split-view-left = { $label }, Split view left + +# Split view tabs display their respective contents side by side +# Displayed within the tooltip on the right tab inside of a tab split view +# "right" corresponds to the visual position. Translate literally; do not swap for RTL languages. +# Variables: +# $label (String): the text label of the tab visible in the tab strip +tabbrowser-tab-label-tab-split-view-right = { $label }, Split view right # Open a new tab next to the current tab and display their contents side by side tab-context-add-split-view =