Navigation
Tabs
Switch between related views in the same place. A segmented pill list by default, or an underlined line list for page sections.
- Source
- src/components/ui/tabs.tsx
- Figma
- Tab · state (active, inactive) × leading (none, icon).
Usage
Included in the GliaKit boilerplate. Import it where you need it:
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";When to use
- Splitting one record or screen into a few peer views, like Overview, Activity and Settings.
- Use the default list for compact view switches inside a card or toolbar.
- Use the line list under a page header for top-level sections of a page.
- For steps that must happen in order, use Stepper.
- For more than six or seven options, or options that change, use a Select.
- For navigating between separate pages with their own URLs, use links styled as tabs so the browser history works.
Examples
Line with icons
variant="line" draws an underline under the active tab. The GliaKit look colors the label and underline violet.
Vertical
orientation="vertical" puts the list beside the content. Up and down arrows move between tabs.
Controlled
Hold the value in state with value and onValueChange to react to the selection.
Disabled tab
A disabled tab is dimmed and skipped by the arrow keys.
API reference
Tabs
Radix Tabs root. Accepts every Radix Tabs.Root prop and native div attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultValue | string | - | Tab selected on first render when uncontrolled. |
| value | string | - | Selected tab when controlled. Use with onValueChange. |
| onValueChange | (value: string) => void | - | Called when the selected tab changes. |
| orientation | "horizontal" | "vertical" | "horizontal" | Horizontal stacks the list above the content; vertical puts the list beside it and switches arrow keys to up and down. |
| activationMode | "automatic" | "manual" | "automatic" | Automatic selects a tab as soon as it gets focus; manual waits for Enter or Space. |
| dir | "ltr" | "rtl" | - | Reading direction for arrow key navigation. |
TabsList
Wraps the triggers. Accepts Radix Tabs.List props and native div attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "line" | "default" | Default is a muted segmented pill with a raised active tab. Line is transparent with an underline under the active tab. |
| loop | boolean | true | Whether arrow key focus wraps from the last tab to the first. |
| className | string | - | Extra classes. The list is w-fit and h-8 when horizontal. |
TabsTrigger
A single tab button. Accepts Radix Tabs.Trigger props and native button attributes. The line underline is an ::after element colored bg-foreground; for the GliaKit violet look pass className="data-active:text-primary after:bg-primary!".
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | - | Identifies the tab and links it to the TabsContent with the same value. Required. |
| disabled | boolean | false | Dims the tab and skips it during keyboard navigation. |
| asChild | boolean | false | Render the child element instead of a <button>. |
TabsContent
The panel for one tab. Accepts Radix Tabs.Content props and native div attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | - | Matches a TabsTrigger value. Required. |
| forceMount | true | - | Keep the panel mounted while inactive, for example to preserve form state or animate it. |
tabsListVariants
The cva function behind TabsList, for styling another element to match.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "line" | "default" | Same variants as TabsList. |
Accessibility
- Built on Radix Tabs: renders role="tablist", role="tab" and role="tabpanel", with aria-selected and aria-controls wired up.
- Arrow keys move between tabs (left and right, or up and down when vertical), Home and End jump to the first and last tab, and disabled tabs are skipped.
- Only the selected tab is in the tab order, so Tab moves from the list straight into the panel.
- Icon-only triggers need an aria-label. Icons next to a text label are decorative.