Tabs
Tab primitives for switching between related panels.
Quick Preview
Composition
Use this public composition when building Tabs:
Tabs
├── TabsListContainer (optional)
│ └── TabsList
│ └── TabsTrigger
│ └── TabsCount (optional)
└── TabsContentUsage
<Tabs defaultValue="overview"><TabsList><TabsTrigger value="overview">Overview</TabsTrigger></TabsList><TabsContent value="overview">Overview</TabsContent></Tabs>Examples
Variants
Use variant on TabsList to choose underline navigation or pill-style secondary tabs.
Count
Render TabsCount inside a TabsTrigger, after the label, to show a count badge. It picks up the active tab and the current size automatically. Reserve counts for meaningful, changing quantities — unread, pending, errors.
Bar container
TabsList is the row of tabs. TabsListContainer is the bar it sits in — wrap the list in one when the bar needs padding the tabs shouldn't inherit, or when something other than a tab has to sit in it.
The container owns the underline variant's baseline rule, so the rule spans the whole bar while the tabs stay inset. Without a container TabsList keeps drawing the rule itself, so existing markup is unaffected.
<TabsListContainer className="px-4">
<TabsList>
<TabsTrigger value="all">All</TabsTrigger>
</TabsList>
<Button variant="ghost" size="sm" className="my-auto ml-auto">Filter</Button>
</TabsListContainer>variant and size stay on TabsList — the container reads the list's variant to decide whether to draw a rule, so a secondary list inside a container can never leave a stray line behind it.
Pad the container along the rule, not across it. The active indicator is pinned to the list's edge — the bottom when horizontal, the right when vertical — so padding on that edge lifts the indicator off the rule. px is safe on a horizontal bar, py on a vertical one.
Sizes
Use size on TabsList to scale the triggers. Defaults to md; sm is compact for dense or in-card contexts, lg for prominent top-level navigation. It also inherits from an ancestor SizeProvider (e.g. inside a Sheet), so tabs match their surrounding surface automatically.
Orientation
Use vertical orientation for side navigation inside settings or detail views. The underline variant becomes a rail down the right of the list — the side the content sits on — with the active indicator riding it, mirroring the baseline under a horizontal bar.
Props
| Prop/API | Type | Default | Description |
|---|---|---|---|
orientation | `"horizontal" | "vertical"` | "horizontal" |
size on TabsList | `"sm" | "md" | "lg"` |
size on Tabs | `"sm" | "md" | "lg"` |
TabsListContainer | div element | - | Optional bar around TabsList; owns the underline rule so padding on the bar doesn't inset it. |
variant on TabsList | `"default" | "line" | "secondary" |
nativeButton on TabsTrigger | boolean | - | Uses native button rendering behavior. |
TabsCount | span element | - | Optional count badge; place inside TabsTrigger after the label. |
className | string | - | Local layout or spacing overrides. |
| native/root props | React component props | - | Passed through to the underlying root or primitive. |
Accessibility
- Preserve the documented Tabs composition so labels, triggers, content, and controls remain connected.
- Provide visible labels or accessible names for interactive controls.
- Preserve the component-provided focus, keyboard, disabled, and invalid-state behavior.
- Do not communicate state with color alone; include text, icons, or helper copy.