Tab Panel
A tab panel is a content panel associated with a tab in a tab bar. It shows the content for the currently selected tab.
Use it as the content companion to a TabBar and TabBarButton. Each panel is labelled by its corresponding tab and is shown only when its tab is selected.
Implementation Notes
- Uses a
<div>withrole="tabpanel"and classtab-panel - When
labelledByis provided, the panel usesaria-labelledby={labelledBy}and omitsaria-label - When
labelledByis not provided, the panel usesaria-label={label}instead - The panel is hidden via the
hiddenattribute whenselectedisfalse - The panel uses
tabindex="0"so keyboard users can scroll the panel content
Props
label: string (required) -- aria-label for the panellabelledBy: string (optional) -- ID of the tab button that controls this panel; when provided, setsaria-labelledbyand the panel does not setaria-labelselected: boolean (defaultfalse) -- whether the panel is the currently selected onechildren: slot -- panel content...restProps: any additional HTML attributes
Usage
<TabBar>
<TabBarButton id="tab-overview" controls="panel-overview" selected>Overview</TabBarButton>
<TabBarButton id="tab-details" controls="panel-details">Details</TabBarButton>
</TabBar>
<TabPanel id="panel-overview" labelledBy="tab-overview" selected={tab === 'overview'}>
Overview content...
</TabPanel>
<TabPanel id="panel-details" labelledBy="tab-details" selected={tab === 'details'}>
Details content...
</TabPanel>
Keyboard Interactions
- Tab: Move focus into and out of the panel
- (Provided by the parent
TabBar) Arrow keys to navigate between tabs - Within the panel, the consumer provides any additional keyboard handling
ARIA
role="tabpanel"on the containeraria-labelledby={labelledBy}when controlled by a tab; otherwisearia-label={label}hiddenreflects!selectedtabindex="0"so the panel itself is keyboard-focusable
When to Use
- Use as the content companion to a
TabBar - Use to switch among related views without navigating to a new page
- Use when only one view is shown at a time
When Not to Use
- Do not use without a corresponding tab in a
TabBar - Do not show multiple selected panels at once
- Do not use for primary navigation between pages — use
NavigationMenu
Composition
Tab panels pair with tabs:
<TabBar label="Sections">
<TabBarButton id="t1" controls="p1" selected>One</TabBarButton>
<TabBarButton id="t2" controls="p2">Two</TabBarButton>
</TabBar>
<TabPanel id="p1" labelledBy="t1" selected>...</TabPanel>
<TabPanel id="p2" labelledBy="t2">...</TabPanel>
Headless
Renders a <div role="tabpanel"> linked to its tab via aria-labelledby. Selection state is controlled by the consumer via the selected prop; animation, lazy loading, and styling are entirely the consumer's responsibility.
Styles
Consumer CSS targets the tab-panel class. Use the hidden attribute selector or [aria-selected] on the parent tab to style transitions. Provide a clear focus indicator on the panel since it is keyboard-focusable.
Testing
- Verify the component renders a
<div>withrole="tabpanel"and classtab-panel - Verify
tabindex="0"is present - Verify
aria-labelledbyis set andaria-labelis absent whenlabelledByis provided - Verify
aria-labelis set andaria-labelledbyis absent whenlabelledByis not provided - Verify
hiddenis set whenselectedisfalse - Verify
hiddenis absent whenselectedistrue - Verify children are rendered inside the panel
Advice
- Designers: Keep tab labels short; communicate the selection clearly with both color and a non-color indicator (underline, weight).
- Developers: Use stable ids on tabs and panels so
aria-labelledbyandaria-controlssurvive re-renders.
Related components
tab-bar— a group of tabs for switching between content panelstab-bar-button— one tab button in a tab group
References
- WAI-ARIA Tabs Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/tabs/
- Adobe Spectrum Tabs: https://spectrum.adobe.com/page/tabs/
- WCAG 1.3.1 Info and Relationships: https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships