Foundations
Tab Panels
Tabs with panels — sliding indicator, keyboard navigation, lazy panels and counts.
2 variantsMIT
Preview
Ship German first: 38% of trial sign-ups last month came from DACH, and the glossary is already reviewed.
Installation
Copies the component into components/ui and installs its dependencies and theme tokens.
pnpm dlx shadcn@latest add https://tuffui.com/r/tab-panels.jsonUsage
Pass your own data and wire the callbacks to your agent runtime.
import { Tab, TabList, TabPanel, Tabs } from "@/components/ui/tab-panels";
<Tabs defaultValue="answer" variant="pills">
<TabList label="Response">
<Tab value="answer">Answer</Tab>
<Tab value="sources" count={sources.length}>Sources</Tab>
</TabList>
<TabPanel value="answer">{answer}</TabPanel>
<TabPanel value="sources" lazy>
<SourceList data={{ sources }} />
</TabPanel>
</Tabs>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| Tabs.value / defaultValue* | string | — | Selected tab. `defaultValue` is required for the uncontrolled case. |
| Tabs.onValueChange | (value: string) => void | — | Called on click or, with automatic activation, on arrow keys. |
| Tabs.variant | "default" | "pills" | "default" | A short bar under the active tab, or a raised pill behind it. |
| Tabs.activation | "automatic" | "manual" | "automatic" | Automatic selects as focus moves; manual moves focus only, Enter or Space selects. |
| TabList.label* | string | — | Accessible name of the tab list. |
| Tab.count | number | — | Small count after the label. |
| TabPanel.lazy | boolean | false | Mount the panel the first time it's selected; it stays mounted after. |