Context
Found during the 2026 Axim-commissioned accessibility audit of Paragon, while documenting Tabs against the APG tabs pattern.
Current behavior (from src/Tabs/__snapshots__/Tabs.test.jsx.snap and React-Bootstrap 1.6.5)
- No tab↔panel association. Tab panels render
role="tabpanel" with aria-labelledby={null}, and tabs render role="tab" with no aria-controls (no id linkage in either direction).
- No roving tabindex. Every tab is an
<a href="#"> and remains in the page tab sequence; the APG pattern expects a single tab stop for the tablist with arrow-key navigation inside. Arrow keys do work (React-Bootstrap AbstractNav: Left/Up previous, Right/Down next, selection follows focus), but Home/End are unsupported and Space does not activate (anchor semantics).
- Overflow "More..." control. The responsive overflow renders a
<button aria-haspopup="true"> nested inside an <a role="tab"> that has no aria-selected — nested interactive elements, and a tab that isn't a tab. Hidden tabs are exposed as dropdown items rather than tabs.
Impact
- (1) Screen reader users landing in a panel get no announcement of which tab labels it; some AT navigation shortcuts between tab and panel don't work. WCAG 1.3.1 Info and Relationships, 4.1.2 Name, Role, Value.
- (2) Extra tab stops slow keyboard traversal of pages with many tabs; missing Space activation is inconsistent with the announced role.
- (3) The nested-interactive structure produces unpredictable focus/announcement behavior in the overflow case.
Suggested direction
Generate stable ids per tab/panel and wire aria-controls/aria-labelledby (fixes 1 without behavior change); consider roving tabindex and Home/End as a follow-up; rework the overflow control so the "More..." toggle is not inside a role="tab" element.
References
Context
Found during the 2026 Axim-commissioned accessibility audit of Paragon, while documenting
Tabsagainst the APG tabs pattern.Current behavior (from
src/Tabs/__snapshots__/Tabs.test.jsx.snapand React-Bootstrap 1.6.5)role="tabpanel"witharia-labelledby={null}, and tabs renderrole="tab"with noaria-controls(noidlinkage in either direction).<a href="#">and remains in the page tab sequence; the APG pattern expects a single tab stop for the tablist with arrow-key navigation inside. Arrow keys do work (React-BootstrapAbstractNav: Left/Up previous, Right/Down next, selection follows focus), but Home/End are unsupported and Space does not activate (anchor semantics).<button aria-haspopup="true">nested inside an<a role="tab">that has noaria-selected— nested interactive elements, and atabthat isn't a tab. Hidden tabs are exposed as dropdown items rather than tabs.Impact
Suggested direction
Generate stable ids per tab/panel and wire
aria-controls/aria-labelledby(fixes 1 without behavior change); consider roving tabindex and Home/End as a follow-up; rework the overflow control so the "More..." toggle is not inside arole="tab"element.References