Tabs
Tabbed content switcher (Radix Tabs) that composes TabsList /
TabsTrigger / TabsContent.
Provides shared variant/size/fullWidth through context so the parts stay
in sync, and tracks the active value to drive the sliding TabsIndicator.
Controlled via value/onValueChange, uncontrolled via defaultValue.
Glazed terracotta hex with a matte, hand-finished surface — a warm, tactile field tile for feature walls and splashbacks.
- Dimensions
- 200 × 200 × 10 mm
- Wear rating
- PEI III
- Finish
- Matte glaze
Veneto Ceramiche · Italy
Clayworks London · United Kingdom
Terra Studio · Portugal
Usage
@desk/ui/components/tabs
<Tabs className="w-96" defaultValue="specs">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="specs">Specs</TabsTrigger>
<TabsTrigger value="suppliers">Suppliers</TabsTrigger>
</TabsList>
<TabsContent className="mt-4" value="overview">
<Text size="sm" variant="muted">
Glazed terracotta hex with a matte, hand-finished surface — a warm,
tactile field tile for feature walls and splashbacks.
</Text>
</TabsContent>
<TabsContent className="mt-4" value="specs">
<DescriptionList>
<DescriptionItem>
<DescriptionTerm>Dimensions</DescriptionTerm>
<DescriptionDetails>200 × 200 × 10 mm</DescriptionDetails>
</DescriptionItem>
<DescriptionItem>
<DescriptionTerm>Wear rating</DescriptionTerm>
<DescriptionDetails>PEI III</DescriptionDetails>
</DescriptionItem>
<DescriptionItem>
<DescriptionTerm>Finish</DescriptionTerm>
<DescriptionDetails>Matte glaze</DescriptionDetails>
</DescriptionItem>
</DescriptionList>
</TabsContent>
<TabsContent className="mt-4" value="suppliers">
<Stack gap="xs">
<Text size="sm">Veneto Ceramiche · Italy</Text>
<Text size="sm">Clayworks London · United Kingdom</Text>
<Text size="sm">Terra Studio · Portugal</Text>
</Stack>
</TabsContent>
</Tabs>Best practices
Reach for
Tabsto swap in-page panels viaTabsContent; when each tab is a route, useTabNavigationinstead (renders links, no panels).Compose
TabsList/TabsTrigger/TabsContent— sharedvariant/size/fullWidthflow through context, so set them onTabs, not each trigger.
Props
Tabs
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "line" | "pill" | "pill" | Indicator style: |
| size | ResponsiveSize | "base" | Trigger sizing on the shared component-size scale — a single token or a
per-breakpoint object like |
| fullWidth | boolean | When true, tabs fill container width with equal proportional widths |
TabsList
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "line" | "pill" | null | undefined | ||
| size | "base" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | null | undefined |
TabsPanel
| Prop | Type | Default | Description |
|---|---|---|---|
| children | import("react").ReactNode | ||
| className | string | ||
| layout | boolean | "position" | "size" | "preserve-aspect" |
TabsTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "line" | "pill" | null | undefined | ||
| size | "base" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | null | undefined | ||
| count | number | Optional count to display alongside the tab label | |
| dot | string | Dot color indicator (CSS color value) | |
| icon | IconComponent | undefined | Leading/trailing icon, rendered through | |
| iconPlacement | "end" | "start" | Which side the icon sits on. Requires |
Also exports
- const
tabsAnatomy - component
TabsContent
Anatomy
Tabs
tabsTabbed content switcher
TabsList
tabs-listContainer for tab triggers
TabsTrigger
tabs-triggerButton to switch tab content
TabsContent
tabs-contentContent panel for each tab
Composition
Builds on
Used by