Components
Tabs
A set of layered sections of content, known as tab panels, displayed one at a time. Use for switching views within a single context.
Preview
A high-level summary of the project.
Live and interactive: switch tabs, then toggle the theme. The track, active pill, and text all remap from Cognition tokens, no dark: classes (the fix for the source file's dark: violations).
Variants
A high-level summary of the project.
<Tabs defaultValue="overview">
<TabsList variant="secondary">
<TabsTrigger variant="secondary" value="overview">Overview</TabsTrigger>
<TabsTrigger variant="secondary" value="analytics">Analytics</TabsTrigger>
</TabsList>
<TabsContent value="overview">…</TabsContent>
</Tabs>A high-level summary of the project.
<TabsList variant="underline">
<TabsTrigger variant="underline" value="overview">Overview</TabsTrigger>
</TabsList>A high-level summary of the project.
<TabsList variant="default">
<TabsTrigger variant="default" value="overview">Overview</TabsTrigger>
</TabsList>The variant goes on both TabsList and TabsTrigger: secondary (segmented), underline (line), and default (accent pills).
With icons
The rendered component.
Drop a Lucide icon in as the first child of a trigger: the [&_svg] rules size and align it.
API
Don't and Do
Don't style the active tab with dark:data-[state=active]:bg-input/30 The legacy tabs.tsx does. And don't use Tabs for navigation between routes; that's a nav, not a tab set.
// Token-driven active state, theme-agnostic
<TabsTrigger variant="secondary" value="overview">
Overview
</TabsTrigger>import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
export function ProjectTabs() {
return (
<Tabs defaultValue="overview">
<TabsList variant="secondary">
<TabsTrigger variant="secondary" value="overview">Overview</TabsTrigger>
<TabsTrigger variant="secondary" value="settings">Settings</TabsTrigger>
</TabsList>
<TabsContent value="overview">…</TabsContent>
<TabsContent value="settings">…</TabsContent>
</Tabs>
);
}Keyboard navigation and roving focus come for free. Set defaultValue (uncontrolled) or value / onValueChange (controlled).