Basel Standard / Docs
Tabs
Section switcher for related views that share one surface and one context.
Tabs partition related content without forcing a route change or opening another overlay. The Swiss treatment keeps the list spare, relies on typographic contrast and the active underline, and fits well in settings screens, record views, and multi-panel editorial surfaces.
Installation
Purchase access, then open /account/install to issue a registry token.Usage
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
<Tabs defaultValue="overview">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="activity">Activity</TabsTrigger>
</TabsList>
<TabsContent value="overview">Overview panel</TabsContent>
<TabsContent value="activity">Activity panel</TabsContent>
</Tabs>
Why This Primitive Exists
Tabs work when several sections belong to the same object or workflow and only one section needs attention at a time.
- Use them for closely related panels with short, stable labels.
- Keep the list compact enough that the active state remains obvious.
- Avoid tabs when each section deserves a route, deep linking, or long-form navigation of its own.
Examples
Basic Section Switching
The default pattern works well for a small set of adjacent panels.
Structured Panels
Tabs become stronger when each panel carries one clear job and the list labels remain terse.
<TabsList>
<TabsTrigger value="inventory">Inventory</TabsTrigger>
<TabsTrigger value="pricing">Pricing</TabsTrigger>
<TabsTrigger value="shipping">Shipping</TabsTrigger>
</TabsList>
In Context
Use tabs inside a card or settings shell when the user should stay with the same record while moving between sections.
Workflow partition
Keep the list short so the sections stay scannable and the current state remains obvious.
Guidance
Keep Labels Short
- One or two words is usually enough for a tab trigger.
- If labels need sentences, the information architecture likely wants a different navigation pattern.
- Avoid stacking too many tabs into one row just because the primitive allows it.
Partition One Context, Not Several
- Tabs should switch between views of the same entity or workflow.
- If each panel has its own unrelated task, separate routes or cards will be clearer.
- Keep the content height changes controlled so the surface does not feel unstable while switching.
Preserve Discoverability
- Choose a meaningful default tab.
- Keep the active tab visually obvious with the built-in underline instead of adding competing decorations.
- Use disabled states sparingly and only when the user can understand why a section is unavailable.
API Reference
Tabs
Tabs composes @radix-ui/react-tabs and forwards the standard Radix root props.
| Export | Type | Notes |
|---|---|---|
Tabs | TabsPrimitive.Root wrapper | Adds the grid-based root layout used across the repo. |
TabsList | TabsPrimitive.List wrapper | Renders the full-width underline rail for triggers. |
TabsTrigger | TabsPrimitive.Trigger wrapper | Handles uppercase trigger styling and active underline state. |
TabsContent | TabsPrimitive.Content wrapper | Adds the standard top spacing between the rail and panel. |
Common Props
| Prop | Applies To | Notes |
|---|---|---|
value | Tabs, TabsTrigger, TabsContent | Controlled tab state and matching panel identity. |
defaultValue | Tabs | Initial tab when uncontrolled. |
onValueChange | Tabs | Called whenever the active tab changes. |
disabled | TabsTrigger | Disables one trigger while preserving layout. |
className | all exports | Extends the base Swiss styling. |