Tabs
A tabbed interface component for organizing content into switchable panels. Supports primary and secondary visual styles, icons in tab triggers, and controlled or uncontrolled selection.
Overview content.
import { Tabs } from "@tenstorrent/vesper/tabs";
import { Typography } from "@tenstorrent/vesper/typography";
export default function TabsDemo() {
return (
<Tabs
defaultValue="overview"
items={[
{
label: "Overview",
value: "overview",
content: <Typography>Overview content.</Typography>,
},
{
label: "Settings",
value: "settings",
content: <Typography>Settings content.</Typography>,
},
{
label: "Activity",
value: "activity",
content: <Typography>Activity content.</Typography>,
},
]}
/>
);
}Options
| Prop | Type | Description | Default |
|---|---|---|---|
variant | "primary" | "secondary" | The visual style variant of the tabs. | "primary" |
items | TabItem[] | The list of tab items. Each has label, value, optional icon, and content. | — |
value | string | The value for the selected tab (controlled mode). | — |
defaultValue | string | The value of the tab to select by default (uncontrolled mode). | — |
onValueChange | (value: string) => void | Callback fired when a new tab is selected. | — |
activationMode | "automatic" | "manual" | Whether a tab is activated on focus (automatic) or on click (manual). | "automatic" |
All other props are forwarded to the underlying <div> element, which wraps the tab list and its panels.
TabItem
| Prop | Type | Description | Default |
|---|---|---|---|
label | string | The text label displayed in the tab trigger. | — |
value | string | A unique value identifying this tab. | — |
icon | ReactNode | An optional icon element rendered before the label. | — |
content | ReactNode | The content rendered in the panel when this tab is active. | — |
Examples
Defining items
Each entry in the items array describes a tab and the panel it reveals: label is the text in the trigger, value identifies the tab, and content is whatever should be rendered when it is active. Tabs are rendered in the order they are provided:
Everything you need to know about this item.
import { Tabs } from "@tenstorrent/vesper/tabs";
import { Typography } from "@tenstorrent/vesper/typography";
export default function BasicTabs() {
return (
<Tabs
defaultValue="details"
items={[
{
label: "Details",
value: "details",
content: (
<Typography>
Everything you need to know about this item.
</Typography>
),
},
{
label: "History",
value: "history",
content: (
<Typography>A log of every change made to this item.</Typography>
),
},
]}
/>
);
}Variants
Tabs can be rendered in one of two variants. The default primary variant is meant for page-level navigation, while the more compact secondary variant suits switching between views inside a smaller container, such as a card or a panel:
The rendered output.
The rendered output.
import { Tabs } from "@tenstorrent/vesper/tabs";
import { Typography } from "@tenstorrent/vesper/typography";
export default function TabsVariants() {
const items = [
{
label: "Preview",
value: "preview",
content: <Typography>The rendered output.</Typography>,
},
{
label: "Code",
value: "code",
content: <Typography>The source code.</Typography>,
},
];
return (
<div
style={{
display: "flex",
flexDirection: "column",
gap: "var(--vesper-spacing-8)",
}}
>
<Tabs variant="primary" defaultValue="preview" items={items} />
<Tabs variant="secondary" defaultValue="preview" items={items} />
</div>
);
}Rendering icons
Pass an icon as a ReactNode to an item's icon prop to render it before that tab's label:
General settings.
import { Gear, Globe } from "@tenstorrent/vesper/icons";
import { Tabs } from "@tenstorrent/vesper/tabs";
import { Typography } from "@tenstorrent/vesper/typography";
export default function TabsWithIcons() {
return (
<Tabs
defaultValue="general"
items={[
{
label: "General",
value: "general",
icon: <Globe />,
content: <Typography>General settings.</Typography>,
},
{
label: "Advanced",
value: "advanced",
icon: <Gear />,
content: <Typography>Advanced settings.</Typography>,
},
]}
/>
);
}Uncontrolled vs controlled
Render Tabs in an uncontrolled fashion to let them keep track of their own selection, passing defaultValue to choose which tab is active initially. If you omit defaultValue, the first tab is selected initially.
If you need to control which tab is selected, pass value alongside onValueChange:
First panel.
import { useState } from "react";
import { Tabs } from "@tenstorrent/vesper/tabs";
import { Typography } from "@tenstorrent/vesper/typography";
export default function ControlledTabs() {
const [tab, setTab] = useState("first");
return (
<Tabs
value={tab}
onValueChange={setTab}
items={[
{
label: "First",
value: "first",
content: <Typography>First panel.</Typography>,
},
{
label: "Second",
value: "second",
content: <Typography>Second panel.</Typography>,
},
]}
/>
);
}Activation mode
By default, moving focus between tab triggers with the arrow keys activates each tab as it receives focus. Pass activationMode="manual" to require Enter, Space, or a click before the panel changes, which is the better choice when a panel's content is expensive to render or fetch:
Focus the tabs and use the arrow keys: the panel only changes once you press Enter or Space.
import { Tabs } from "@tenstorrent/vesper/tabs";
import { Typography } from "@tenstorrent/vesper/typography";
export default function ManualTabs() {
return (
<Tabs
activationMode="manual"
defaultValue="metrics"
items={[
{
label: "Metrics",
value: "metrics",
content: (
<Typography>
Focus the tabs and use the arrow keys: the panel only changes once
you press Enter or Space.
</Typography>
),
},
{
label: "Logs",
value: "logs",
content: <Typography>Logs panel.</Typography>,
},
]}
/>
);
}