Problem Statement
Tabs are useful for organizing content into logical groups, allowing users to toggle between different views without loading new pages. However, developers often create tabs that are unnavigable for screen reader users and keyboard-only navigators.
We need to build a reusable and accessible Tabs component in React. Users should be able to toggle content panels, and keyboard users must be able to shift focus and activate tabs using arrow navigation keys according to WAI-ARIA guidelines.
Requirements
Functional
- Dynamic Content: Accept an array of tab objects, where each object contains a unique
id, alabel(ReactNode), and acontent(ReactNode). - Active Tab State: Track which tab is currently selected, displaying only that tab's associated content panel.
- Keyboard Navigation:
- Arrow keys (
ArrowLeft/ArrowRight) move focus to the adjacent tab headers. Focus moves from the last tab header to the first (and vice versa) in a cyclic loop. - Moving focus to a tab should immediately select and display that tab's panel content (automatic activation pattern).
Homemoves focus and selects the first tab header.Endmoves focus and selects the last tab header.
- Arrow keys (
- ARIA Semantic Attributes:
- Set
role="tablist"on the element wrapping all tab headers. - Set
role="tab"on each individual header trigger button. - Set
role="tabpanel"on each panel wrapping active content. - Define
aria-selected(true/false) on each tab header trigger. - Define
aria-controlson the tab trigger pointing to the ID of the corresponding tabpanel. - Define
aria-labelledbyon the tabpanel pointing to the ID of its corresponding tab trigger. - Set
tabIndex={0}on the active tab header andtabIndex={-1}on all inactive tab headers to ensure the tablist itself holds only one tab stop in page navigation.
- Set
Non-Functional
- Ensure styling indicates keyboard focus clearly (focus ring).
- Expose strong TypeScript interfaces for component parameters.
Concepts Tested
- WAI-ARIA Tab list design specifications.
- Dynamic DOM focus adjustments via React references.
- Keyboard Event mapping (
onKeyDown) and browser default prevention.
