Tabs
Organize content into switchable panels with various styles and layouts.
Basic Tabs
Snippet
import { Tabs, TabPanel } from '@creo-team/buzz-ui/server'
const [tab, setTab] = useState('overview')
<Tabs
items={[
{ key: 'overview', label: 'Overview' },
{ key: 'features', label: 'Features' }
]}
value={tab}
onChange={setTab}
/>
<TabPanel value="overview" selectedValue={tab}>
<p>Overview content</p>
</TabPanel>
<TabPanel value="features" selectedValue={tab}>
<p>Features content</p>
</TabPanel>
Variants
Default
Pills
Underline
Buttons
Glass
Snippet
<Tabs variant="default" ... />
<Tabs variant="pills" ... />
<Tabs variant="underline" ... />
<Tabs variant="buttons" ... />
<Tabs variant="glass" ... />
Sizes
Snippet
<Tabs size="sm" ... />
<Tabs size="md" ... />
<Tabs size="lg" ... />
With Icons & Badges
Snippet
const items = [
{
key: 'home',
label: 'Home',
icon: <Home className="h-4 w-4" />
},
{
key: 'users',
label: 'Users',
icon: <Users className="h-4 w-4" />,
badge: 12
},
{
key: 'notifications',
label: 'Notifications',
icon: <Bell className="h-4 w-4" />,
disabled: true
}
]
<Tabs items={items} value={tab} onChange={setTab} />
Full Width
Snippet
<Tabs items={items} value={tab} onChange={setTab} fullWidth />
<Tabs items={items} value={tab} onChange={setTab} variant="underline" fullWidth />
Using Button Groups as Tabs
You can achieve tab-like behavior using button groups for simpler use cases:
Grid view selected
Snippet
import { Button } from '@creo-team/buzz-ui/client'
const [view, setView] = useState('grid')
<div className="inline-flex gap-0.5 rounded-xl border border-[var(--c-border)] bg-[var(--c-surface)]/50 p-0.5">
{options.map((option) => (
<Button
key={option.value}
variant={view === option.value ? "subtle" : "ghost"}
size="sm"
selected={view === option.value}
onClick={() => setView(option.value)}
>
{option.label}
</Button>
))}
</div>
Tabs API Reference
Prop | Type | Default | Description |
---|---|---|---|
items * | TabItem[] | — | Array of tab items |
value * | string | — | Currently selected tab key |
onChange * | (key: string) => void | — | Callback when tab is selected |
variant | 'default' | 'pills' | 'underline' | 'buttons' | 'glass' | 'default' | Visual style variant |
size | 'sm' | 'md' | 'lg' | 'md' | Size variant |
fullWidth | boolean | false | Stretch tabs to full container width |
className | string | — | Additional CSS classes |
TabItem Interface
Prop | Type | Default | Description |
---|---|---|---|
key * | string | — | Unique identifier for the tab |
label * | React.ReactNode | — | Tab label content |
icon | React.ReactNode | — | Optional icon element |
badge | string | number | — | Optional badge content |
disabled | boolean | — | Disable tab interaction |
TabPanel API Reference
Prop | Type | Default | Description |
---|---|---|---|
value * | string | — | Tab key this panel corresponds to |
selectedValue * | string | — | Currently selected tab key |
children * | React.ReactNode | — | Panel content |
className | string | — | Additional CSS classes |
Accessibility Note: Tabs are fully accessible with proper ARIA attributes, keyboard navigation support, and focus management. The active tab is clearly indicated visually and programmatically.
Full API: /components/tabs/api