Tabs
Panels that share one place on the page, one shown at a time. Tabs.Root owns the selected value. Tabs.List is the role="tablist"; each Tabs.Tab is a native button with role="tab", and each Tabs.Panel is a role="tabpanel" labelled by its tab. A tab and a panel pair by value.
The list holds one tab stop, on the selected tab. Arrow keys, Home and End move between tabs through useRovingFocus. Left and Right swap in a right-to-left page. A disabled tab is a native disabled button, so arrow keys skip it.
<Tabs.Root defaultValue="account">
<Tabs.List aria-label="Settings">
<Tabs.Tab value="account">Account</Tabs.Tab>
<Tabs.Tab value="billing">Billing</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="account">…</Tabs.Panel>
<Tabs.Panel value="billing">…</Tabs.Panel>
</Tabs.Root>
Name, email and password.
activation="automatic" (default) selects a tab as soon as focus moves to it from another tab. Focus entering the list from outside selects nothing, even when it lands on a fallback tab because the selected one is disabled. Use activation="manual" when a panel is slow to render: arrow keys only move focus, and Enter, Space or a click selects. When focus leaves the list, its tab stop returns to the selected tab. orientation="vertical" puts the list beside the panels and moves with Up and Down.
The root takes value with onValueChange, or defaultValue. One tab is always selected, so there is no empty state. Only the selected panel renders its children; pass keepMounted to keep a hidden panel's state, such as a half-filled form. A panel is a Tab stop by default, so a screen reader user reaches its text; pass tabIndex={-1} when the panel starts with a control of its own.
Arrow keys move focus. Enter or Space shows the panel.
Selected: overview
There is no native tabs element. An exclusive <details name> group looks similar but has no tab semantics or arrow keys, so it is an accordion, not tabs.
When to use
When: Switch between sibling views of the same object in one place, such as settings sections or report views, where one view shows at a time.
When not: Moving to another page → links. A list of actions → Menu. Several sections open at once, or long content read top to bottom → headings or <details>.
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| value | string | no | — | Controlled selected tab. Pass with onValueChange. |
| defaultValue | string | no | — | Initial selected tab when uncontrolled. |
| onValueChange | (value: string) => void | no | — | Fires with the next selected tab. |
| orientation | "horizontal" | "vertical" | no | "horizontal" | Arrow keys, layout and aria-orientation. |
| activation | "automatic" | "manual" | no | "automatic" | automatic selects on focus. manual waits for Enter, Space or a click. |
| children | React.ReactNode | no | — | Tabs.List and Tabs.Panel. |
| className | string | no | — | Optional class on the root. |
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| aria-label | string | no | — | Names the tablist when no visible caption exists. |
| aria-labelledby | string | no | — | Id of a visible caption for the tablist. |
| children | React.ReactNode | no | — | Tabs.Tab children. |
| className | string | no | — | Optional class on the tablist. |
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| value | string | yes | — | Matches a Tabs.Panel value. |
| disabled | boolean | no | — | Native disabled. Skipped by arrow keys. |
| children | React.ReactNode | no | — | Tab label. |
| className | string | no | — | Optional class on the tab. |
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| value | string | yes | — | Matches a Tabs.Tab value. |
| keepMounted | boolean | no | false | Keep children mounted while hidden, so their state survives a tab switch. |
| children | React.ReactNode | no | — | Panel content. |
| className | string | no | — | Optional class on the panel. |