Usage
Tabs pairs triggers with linked content panels on a single route. It fits settings categories, incident summaries with peer sections, and dashboards where each tab reveals closely related content without an additional navigation hop. The mental model is "peer sections that share context"—if the content belongs on separate routes or users expect bookmarkable URLs per panel, reach for TabNav instead. Tabs is the pattern that stays on one URL; the triggers and panels are programmatically associated for assistive technologies so the label, state, and content are announced together.
Live transcript of the active call updates here in real time.
Incident detail split across "Summary", "Transcript", and "Metadata"; settings panels grouped into "General", "Privacy", and "Integrations"; a QA form that splits scoring, evidence, and notes. Operators switch among panels frequently while the entity in focus stays the same.
Tabs let an operator flip between "Calls", "Shifts", and "Incidents" views of the same time range without navigating away. The shared control bar (filters, time range) stays visible across panels.
On narrow dispatch rails and mobile, tabs are a small-footprint way to offer three to seven peer views.
Use TabMenu. Tabs create linked content panels; a filter strip changes what a single panel renders.
Use TabNav. Users expect a link-based component to change the URL and be bookmarkable; tabs imply a single-route container.
Seven is already crowded. Above that, restructure the information architecture: a sidebar, a stepped flow, or nested pages.
Use Accordion when the mental model is "a tall list where I open a couple of sections", not "a row of peer panels I switch between."
| Axis | Values | When to pick it |
|---|---|---|
| Orientation | horizontal, vertical | Horizontal for short label lists atop panels; vertical when labels are long or sit beside a single wide panel |
| State | uncontrolled (defaultValue) or controlled (value + onValueChange) | Controlled when panel changes drive analytics, URL state, or cross-panel validation |
Tabs wraps a TabsList of TabsTrigger buttons followed by one TabsContent panel per value. Labels sit in the trigger; optional counts use the counter affordance so operators can see magnitude without opening the tab. Keep labels short and parallel; verbose labels crowd the list and push counts off-screen.
counter prop; do not bake numbers into label text, where translations will break the rhythm.formatMessage. Even short English labels lengthen in German or French; test the longest expected translation inside the list width.defaultValue covers static settings views where no other UI depends on the active tab.value + onValueChange when syncing to URL params, analytics, or cross-panel validation. Drive the value from the source of truth; do not fork state across two parents.Do
Don't
Radix implements the WAI-ARIA Tabs pattern: tablist, tab, and tabpanel roles with arrow-key navigation and focus management. The app still supplies the list's accessible name and the trigger labels. See Accessibility for the full keyboard map, announcement sequences, and labelling patterns.
On this page