Tabs
Explore interactive examples and all component variations in our Storybook.
The Tabs component organizes content into multiple panels with accessible keyboard navigation, focus management, and customizable sizing. Supports two visual variants — the default pill style and an outline file-tab style — as well as controlled and uncontrolled modes.
Basic Usage
Sizes
Pass the same size to both TabsList and each TabsTrigger. Available sizes: sm, md (default), lg, xl.
sm
md
lg
xl
With Icons
Place a Lucide icon before the label inside TabsTrigger. The trigger handles spacing automatically.
Public Profile
Update your photo and personal details.
Outline Variant
Set variant="outline" on the Tabs root for a file-tab appearance — an underline connects the list to the content area, and the active tab appears raised above it. Ideal for code editors, document viewers, or any multi-panel interface that should feel like open files.
'use client'
import { cn } from '@/lib/utils'
Collapse Label
Add collapseLabel to a TabsTrigger to show only the icon when that tab is inactive. The label reappears when the tab becomes active. This keeps the tab bar compact while still surfacing context on selection. The label remains accessible to screen readers at all times.
collapseLabel works with both variants and can be mixed — some tabs collapse while others always show their label:
Controlled
Pass value and onValueChange to control the active tab from outside:
Properties
Tabs
| Property | Type | Default | Description |
|---|---|---|---|
defaultValue | string | — | Initial active tab (uncontrolled). |
value | string | — | Active tab value (controlled). |
onValueChange | (value: string) => void | — | Callback fired when the active tab changes. |
variant | "default" | "outline" | "default" | Visual style. default is a pill/segmented control; outline looks like file tabs. |
orientation | "horizontal" | "vertical" | "horizontal" | Layout direction of the tab list. |
dir | "ltr" | "rtl" | — | Reading direction. |
activationMode | "automatic" | "manual" | "automatic" | Whether focus automatically activates a tab. |
className | string | — | Additional CSS classes. |
TabsList
| Property | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | "xl" | "md" | Height of the tab list. |
loop | boolean | true | Whether arrow-key navigation wraps around. |
className | string | — | Additional CSS classes. |
TabsTrigger
| Property | Type | Default | Description |
|---|---|---|---|
value | string | — | Required. Unique identifier linking this trigger to its content panel. |
size | "sm" | "md" | "lg" | "xl" | "md" | Size of the trigger. Should match the TabsList size. |
collapseLabel | boolean | false | When true, hides the text label when the tab is inactive, showing only the icon. Requires an icon as the first child. The label remains visible to screen readers. |
disabled | boolean | false | Prevents selection and keyboard navigation. |
className | string | — | Additional CSS classes. |
TabsContent
| Property | Type | Default | Description |
|---|---|---|---|
value | string | — | Required. Matches the corresponding TabsTrigger value. |
forceMount | boolean | false | Keep the panel in the DOM even when inactive (useful for animating exit). |
className | string | — | Additional CSS classes. |
Accessibility
- Keyboard navigation —
←/→(or↑/↓for vertical) move between tabs;Home/Endjump to first/last. Focus loops by default. - Roving tabindex — only the active tab is in the natural tab sequence; inactive tabs are reachable via arrow keys.
- ARIA —
role="tablist",role="tab",role="tabpanel",aria-selected,aria-controls, andaria-labelledbyare set automatically. collapseLabel— collapsed labels usesr-onlyso screen readers still announce the full tab name.