Tabs
A set of layered sections of content that display one panel at a time.
$ npx @beaket/ui add tabsAccount Settings
Manage your account settings and preferences.
Source
import { Tabs } from "@/components/ui/tabs";
const args = {};
const render = () => (
<Tabs defaultValue="account" className="max-w-md">
<Tabs.List>
<Tabs.Trigger value="account">Account</Tabs.Trigger>
<Tabs.Trigger value="password">Password</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="account">
<div className="p-4">
<h3 className="font-medium">Account Settings</h3>
<p className="text-fg-muted mt-2 text-sm">Manage your account settings and preferences.</p>
</div>
</Tabs.Content>
<Tabs.Content value="password">
<div className="p-4">
<h3 className="font-medium">Password Settings</h3>
<p className="text-fg-muted mt-2 text-sm">Update your password and security settings.</p>
</div>
</Tabs.Content>
</Tabs>
);
export default function Example() {
return render();
}Examples
All States
Two Tabs
First tab content
With Disabled Tab
First enabled tab
Many Tabs
Content 1
Source
import { Tabs } from "@/components/ui/tabs";
export default () => (
<div className="space-y-8">
<div>
<h3 className="mb-4 text-sm font-medium">Two Tabs</h3>
<Tabs defaultValue="tab1" className="max-w-sm">
<Tabs.List>
<Tabs.Trigger value="tab1">First</Tabs.Trigger>
<Tabs.Trigger value="tab2">Second</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="tab1">
<div className="text-fg-muted p-4 text-sm">First tab content</div>
</Tabs.Content>
<Tabs.Content value="tab2">
<div className="text-fg-muted p-4 text-sm">Second tab content</div>
</Tabs.Content>
</Tabs>
</div>
<div>
<h3 className="mb-4 text-sm font-medium">With Disabled Tab</h3>
<Tabs defaultValue="enabled1" className="max-w-md">
<Tabs.List>
<Tabs.Trigger value="enabled1">Enabled</Tabs.Trigger>
<Tabs.Trigger value="disabled" disabled>
Disabled
</Tabs.Trigger>
<Tabs.Trigger value="enabled2">Also Enabled</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="enabled1">
<div className="text-fg-muted p-4 text-sm">First enabled tab</div>
</Tabs.Content>
<Tabs.Content value="enabled2">
<div className="text-fg-muted p-4 text-sm">Second enabled tab</div>
</Tabs.Content>
</Tabs>
</div>
<div>
<h3 className="mb-4 text-sm font-medium">Many Tabs</h3>
<Tabs defaultValue="t1" className="max-w-lg">
<Tabs.List>
<Tabs.Trigger value="t1">Tab 1</Tabs.Trigger>
<Tabs.Trigger value="t2">Tab 2</Tabs.Trigger>
<Tabs.Trigger value="t3">Tab 3</Tabs.Trigger>
<Tabs.Trigger value="t4">Tab 4</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="t1">
<div className="text-fg-muted p-4 text-sm">Content 1</div>
</Tabs.Content>
<Tabs.Content value="t2">
<div className="text-fg-muted p-4 text-sm">Content 2</div>
</Tabs.Content>
<Tabs.Content value="t3">
<div className="text-fg-muted p-4 text-sm">Content 3</div>
</Tabs.Content>
<Tabs.Content value="t4">
<div className="text-fg-muted p-4 text-sm">Content 4</div>
</Tabs.Content>
</Tabs>
</div>
</div>
);Props
| Name | Type | Default | Description |
|---|---|---|---|
| Content.keepMounted | boolean | false | Keep this panel's state — scroll position, uncommitted input, anything in a hook — while another tab is active. Off by default, which is Radix's behavior: inactive panels unmount and their state is destroyed. Uses React 19.2's `<Activity mode="hidden">`, the middle ground between unmounting and Radix's `forceMount`: state is preserved, effects are torn down, and re-rendering is deprioritized. Requires React >= 19.2. |