Skip to main content

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" of role="tab" buttons with aria-selected; label the list with aria-label and link panels via aria-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 fire onChange.
  • Roving tabindex: Tab enters the list on the selected tab and leaves it in one step.

Props​

Tabs​

PropTypeDefaultDescription
defaultValuestring—Uncontrolled initial tab value.
onChange((event: MouseEvent<HTMLButtonElement, MouseEvent>, value: string) => void)—Fires with the triggering event and the newly selected tab value.
scrollablebooleanfalseScrollable tabs size to content and scroll horizontally instead of filling.
valuestring—Controlled selected tab value.
variantenumprimaryIndicator style.

Tab​

PropTypeDefaultDescription
iconReactNode—Optional icon (shown above the label).
labelReactNode—Tab label.
value *string—Identifies the tab; matched against the parent `Tabs` value.