TrademarkTrademark
Docs
Ctrl k
Search docs...
Components

Tabs

Updated: October 10, 2026
View on GitHub
Soon
Not released yet. This is on main and is not in any published version yet. It will not install today.

Tabs shows one panel of content at a time and a list of tabs to switch between them. It is four parts matched by value: Tabs holds the state, TabList holds the Tab buttons, and each TabPanel holds the content for one tab. The parts are separate so the list and the panels can sit in any layout.

Each Tab is a ToggleButton with the tab role, so it takes the same props: prefixIcon, suffixIcon, size, variant, disabled. Tabs, TabList and TabPanel are Flex containers and take every Flex prop.

Vertical

orientation="vertical" puts the list beside the panels and switches the arrow keys to Up and Down. Tabs in a vertical list fill its width and align their label to the start, which is the settings-sidebar layout. Change the direction at a breakpoint with the usual responsive props: here the list moves above the panel on small screens.

Controlled

Pass value and onChange when something else owns the selection: a URL search param, say, so a reload opens the same tab. onChange is not called for the tab that is already selected. Without value, Tabs keeps its own state and starts on defaultValue, or on the first enabled tab if there is none.

Keyboard

Only the selected tab is in the page's Tab order, so Tab moves from the list to the panel rather than through every tab.

Key
Does
Left / RightPrevious and next tab, wrapping at the ends (Up / Down when vertical). Swapped in a right-to-left layout.
Home / EndFirst and last tab.
Enter / SpaceSelect the focused tab, when activation="manual".

By default a tab is selected as soon as the arrow keys reach it. Set activation="manual" when showing a panel is slow, such as one that fetches: the arrow keys then only move focus, and Enter or Space selects.

Disabled tabs stay visible and the arrow keys skip them.

Panels

An unselected panel renders nothing inside it, so its effects stop and its state resets. Pass keepMounted to keep a panel's content mounted and hidden instead: a form with unsaved input, a video that should keep its position.

Every tab is wired to its panel with aria-controls, and every panel is labelled by its tab, so a screen reader announces "Security, tab panel". A panel is focusable, so a keyboard user can reach one that has no controls of its own. A tab with no TabPanel (a list of tabs that changes the route, for instance) gets no aria-controls.

Give the list a name with aria-label (or aria-labelledby) when no heading on the page names it.

API reference

Tabs

Type
Default
value
The selected tab's value, when the host owns the state. Pair with onChange.
string—
defaultValue
The tab selected first when Tabs keeps its own state. Without it, the first enabled tab.
string—
onChange
Called with the newly selected tab's value.
(value: string) => void—
orientation
Which arrow keys move between tabs, and whether the list sits above or beside the panels.
horizontalvertical
horizontal
activation
automatic selects a tab when the arrow keys reach it; manual waits for Enter or Space.
automaticmanual
automatic
children
A TabList and its TabPanels, in any layout.
React.ReactNode—
…and every FlexProps propinherited—

TabList

Type
Default
children
The Tab buttons.
React.ReactNode—
…and every FlexProps propinherited—

Tab

Type
Default
valuerequired
Matches the TabPanel this tab shows, and is what onChange reports.
string—
children
The tab's text.
React.ReactNode—
disabled
Visible, not selectable, skipped by the arrow keys.
booleanfalse

TabPanel

Type
Default
valuerequired
The value of the Tab that shows this panel.
string—
keepMounted
Keep the content mounted, hidden, while another tab is selected.
booleanfalse
children
The panel's content.
React.ReactNode—
…and every FlexProps propinherited—
Edit this page on GitHub
TrademarkTrademark
Built with curiosity by Lorant One and the Design Engineers Club