Tabs
MD3 tabs: a role="tablist" row of Tabs with a sliding active indicator,
in primary and secondary variants, fixed or scrollable.
Variants
primary tabs sit at the top of a content pane under an app bar and use a
content-width indicator; secondary tabs divide content within a pane and
use a full-width line.
<Tabs variant="secondary" defaultValue="flights" aria-label="Trip">
<Tab value="flights" label="Flights" />
<Tab value="hotels" label="Hotels" />
</Tabs>
Icons
icon shows above the label (icon + label tabs are 64dp tall).
Scrollable
Fixed tabs (default) split the row into equal widths. scrollable tabs size
to their content and scroll horizontally; the selected tab is scrolled to
the center whenever the selection changes.
<Tabs scrollable value={value} onChange={(event, next) => setValue(next)}>…</Tabs>
With panels
Tabs are controlled (value + onChange) or uncontrolled (defaultValue).
There is no panel component — render the panel yourself and link it with
id / aria-controls / aria-labelledby.
Search one-way and round-trip flights.
const [value, setValue] = useState('flights')
<Tabs aria-label="Trip planner" value={value} onChange={(event, next) => setValue(next)}>
<Tab value="flights" label="Flights" id="tab-flights" aria-controls="panel" />
<Tab value="hotels" label="Hotels" id="tab-hotels" aria-controls="panel" />
</Tabs>
<div role="tabpanel" id="panel" aria-labelledby={`tab-${value}`} tabIndex={0}>
{panels[value]}
</div>
Accessibility
role="tablist"ofrole="tab"buttons witharia-selected; label the list witharia-labeland link panels viaaria-controls.- Manual activation (WAI-ARIA APG): ← / →
(mirrored in RTL), Home and End move focus only;
Space / Enter select the focused tab and fire
onChange. Arrow keys never fireonChange. - Roving tabindex: Tab enters the list on the selected tab and leaves it in one step.
Props
Tabs
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | string | — | Uncontrolled initial tab value. |
onChange | ((event: MouseEvent<HTMLButtonElement, MouseEvent>, value: string) => void) | — | Fires with the triggering event and the newly selected tab value. |
scrollable | boolean | false | Scrollable tabs size to content and scroll horizontally instead of filling. |
value | string | — | Controlled selected tab value. |
variant | enum | primary | Indicator style. |
Tab
| Prop | Type | Default | Description |
|---|---|---|---|
icon | ReactNode | — | Optional icon (shown above the label). |
label | ReactNode | — | Tab label. |
value * | string | — | Identifies the tab; matched against the parent `Tabs` value. |