Overview
Tabs is a Base UI-powered tab system with Kuzenbo styling and compound subcomponents.
It supports horizontal and vertical orientation, className callbacks, and optional animated indicator composition.
Use tabs when users should switch between sibling content panels without route changes.
Installation
Import
import {
Tabs,
TabsContent,
TabsIndicator,
TabsList,
TabsTrigger,
} from "@kuzenbo/core/ui/tabs";
Basic Usage
import { Tabs } from "@kuzenbo/core/ui/tabs";
export function TabsBasicExample() {
return (
<Tabs defaultValue="overview">
<Tabs.List variant="default">
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="projects">Projects</Tabs.Trigger>
<Tabs.Trigger value="account">Account</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="overview">Overview panel content.</Tabs.Content>
<Tabs.Content value="projects">Projects panel content.</Tabs.Content>
<Tabs.Content value="account">Account panel content.</Tabs.Content>
</Tabs>
);
}
Full-Width Tabs
import { Tabs } from "@kuzenbo/core/ui/tabs";
export function TabsFullWidthExample() {
return (
<Tabs defaultValue="overview">
<Tabs.List fullWidth variant="line">
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="projects">Projects</Tabs.Trigger>
<Tabs.Trigger value="account">Account</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="overview">Overview panel content.</Tabs.Content>
<Tabs.Content value="projects">Projects panel content.</Tabs.Content>
<Tabs.Content value="account">Account panel content.</Tabs.Content>
</Tabs>
);
}
Advanced Usage
import { Tabs } from "@kuzenbo/core/ui/tabs";
export function TabsAdvancedExample() {
return (
<Tabs
className="rounded-md border border-border p-2"
defaultValue="overview"
>
<Tabs.List activateOnFocus variant="line">
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="projects">Projects</Tabs.Trigger>
<Tabs.Trigger value="account">Account</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="overview">Overview panel content.</Tabs.Content>
<Tabs.Content value="projects">Projects panel content.</Tabs.Content>
<Tabs.Content value="account">Account panel content.</Tabs.Content>
</Tabs>
);
}
Unified Size Contract
Tabs.List uses shared UISize tokens:
xs | sm | md | lg | xl
- default is
md
Family-specific metrics for tab surfaces:
- List minimum row height per token.
- Trigger height/padding/text density per token.
- Indicator radius/density follows the same token.
Precedence rule:
Tabs.Trigger/Tabs.Indicator size ?? Tabs.List size ?? "md"
Tabs.Trigger and Tabs.Indicator inherit from Tabs.List; size is set at list level.
import { Tabs } from "@kuzenbo/core/ui/tabs";
export function TabsVariantsAndSizes() {
return (
<Tabs
className="rounded-md border border-border p-2"
defaultValue="overview"
>
<Tabs.List size="lg" variant="pill">
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="projects">Projects</Tabs.Trigger>
<Tabs.Trigger value="account">Account</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="overview">Overview panel content.</Tabs.Content>
<Tabs.Content value="projects">Projects panel content.</Tabs.Content>
<Tabs.Content value="account">Account panel content.</Tabs.Content>
</Tabs>
);
}
API Reference
Tabs
Root tabs container built on Base UI Tabs.
Initial tab value (uncontrolled).
Current tab value (controlled).
Callback when tab changes.
orientation
'horizontal' | 'vertical'
default:"horizontal"
Tab layout direction.
TabsList
Container for tab triggers with variant styles.
variant
'default' | 'line' | 'pill'
default:"default"
Visual style variant.
Size of the tab list: xs | sm | md | lg | xl.
Whether triggers should expand to fill available width.
Whether to activate tabs when focused via keyboard.
TabsTrigger
Interactive tab button.
Unique identifier for this tab.
Whether the tab is disabled.
TabsContent
Panel content for a specific tab.
Tab value this content corresponds to.
TabsIndicator
Animated active tab indicator (mainly for default variant).
Custom styles for the indicator.
Accessibility
- Base UI handles ARIA tabs semantics (
tablist, tab, tabpanel).
- Keep trigger labels concise and unique.
- Disabled triggers should remain visibly disabled and excluded from activation flow.
SSR and RSC
- Tabs interactions are client-side.
TabsIndicator uses renderBeforeHydration to reduce hydration mismatch risk for indicator position.
Styling and Tokens
- Tabs list/trigger defaults are tokenized (
bg-muted, text-muted-foreground, text-foreground, border-border).
- Keep custom tab surfaces on semantic tokens and avoid raw palette classes.
- For vertical tabs, use layout classes on root and wrap content in a flexible container.
Troubleshooting
- Panel does not render: ensure every
Tabs.Content value matches an existing trigger value.
- Indicator not visible in default variant: include
<Tabs.Indicator /> inside Tabs.List.
- Arrow keys move focus but do not activate: set
activateOnFocus on Tabs.List.
- Disabled tab still switching: verify
disabled is applied on Tabs.Trigger.