Tab / TabContainer: Tab expand button (overflow arrow) incorrectly exposed as interactive element to screen readers
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.8k
- Forks
- 285
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 59
Description
Description
In the TabContainer component (used internally by ObjectPage), when a Tab has sub-items and its own content (the "two-click area" pattern), the expand/overflow arrow button is rendered as a fully interactive <ui5-button> element. This causes screen readers (e.g., JAWS in VPC mode) to announce it as a separate "More" menu button and expose it in the Button List.
In the SAPUI5 reference implementation (sap.uxap.ObjectPageLayout), the equivalent overflow arrow icon is treated as decorative — it uses role="presentation" and aria-hidden="true", so only the tab itself is exposed to screen readers.
Affected Component
@ui5/webcomponents — Tab / TabContainer (version 2.24.0)
Reproduction Steps
- Create an ObjectPage with an ObjectPageSection that contains multiple ObjectPageSubSection children:
<ObjectPage>
<ObjectPageSection titleText="General Information">
<ObjectPageSubSection titleText="Details">...</ObjectPageSubSection>
<ObjectPageSubSection titleText="Description">...</ObjectPageSubSection>
</ObjectPageSection>
<ObjectPageSection titleText="Additional Settings">...</ObjectPageSection>
</ObjectPage>
- Open the page with JAWS screen reader enabled
- Open the JAWS Button List (INSERT + F7) or navigate in Virtual PC Cursor mode
- Observe that a "More" button appears as a separate actionable element next to the "General Information" tab
Expected Behavior (SAPUI5 Reference)
The expand/overflow arrow should be decorative only, matching the SAPUI5 sap.uxap.ObjectPageLayout behavior:
<!-- SAPUI5 reference: expand icon is decorative -->
<span role="presentation" aria-hidden="true" aria-label="More"
class="sapMITBFilterExpandIcon">
</span>
role="presentation"— not exposed to accessibility treearia-hidden="true"— invisible to screen readers- No separate focus stop or interactive element
- The tab itself has
aria-haspopup="menu"to indicate it opens a submenu
Reference sample: https://ui5.sap.com/#/entity/sap.uxap.ObjectPageSection/sample/sap.uxap.sample.ObjectPageSection
Actual Behavior (UI5 Web Components)
The expand button is rendered as an interactive <ui5-button> in TabInStripTemplate.js:
// When requiresExpandButton === true (two-click area)
<div class="ui5-tab-expand-button">
<Button
icon={slimArrowDownIcon}
design="Transparent"
tabindex={-1}
tooltip={this.expandButtonTitle} // "More"
accessibilityAttributes={{ hasPopup: "menu" }}
/>
</div>
This causes:
- JAWS announces: "More button menu Press down arrow key to open subitems menu"
- The button appears in the JAWS Button List as a separate actionable item
- Users may be confused about the relationship between the tab and the "More" button
Root Cause
In Tab.js, the requiresExpandButton getter returns true when a tab has sub-items AND its own content:
get requiresExpandButton() {
return this.items.length > 0 && this._isTopLevelTab && this.hasOwnContent;
}
This triggers the rendering of a full <Button> component instead of a decorative icon.
Suggested Fix
The expand button in the "two-click area" pattern should follow the SAPUI5 reference approach:
- Replace the interactive
<Button>with a non-interactive icon element - Add
role="presentation"andaria-hidden="true"to the expand icon - Keep
aria-haspopup="menu"on the parent tab element (already present) - The click handler can remain on the icon's container
<div>without requiring it to be an accessible button
Environment
@ui5/webcomponents: 2.24.0@ui5/webcomponents-react: 2.24.1- Screen reader: JAWS (latest)
- Browser: Chrome (latest)
Impact
- Accessibility: Violates WCAG expectations — decorative elements should not be exposed to assistive technology
- Usability: Confuses screen reader users who encounter an unexpected "More" button separate from the tab
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in TabInStripTemplate.js, where the two-click-area expand control is rendered, and inspect Tab.js for the requiresExpandButton condition. Reproduce the ObjectPage case with a screen reader, then verify that the arrow is decorative and hidden from the accessibility tree while the parent tab retains aria-haspopup="menu".
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- accessibility, frontend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100