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:
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 =