Tabs
Switch between related panels. The active-tab indicator physically slides between tabs — seamui's layout-animation pattern.
Manage your account. The indicator springs between tabs.
tsx
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/registry/seam/ui/tabs"
export default function TabsDemo() {
return (
<Tabs defaultValue="account" className="w-80">
<TabsList>
<TabsTrigger value="account">Account</TabsTrigger>
<TabsTrigger value="password">Password</TabsTrigger>
<TabsTrigger value="team">Team</TabsTrigger>
</TabsList>
<TabsContent
value="account"
className="text-muted-foreground pt-2 text-sm"
>
Manage your account. The indicator springs between tabs.
</TabsContent>
<TabsContent
value="password"
className="text-muted-foreground pt-2 text-sm"
>
Change your password here.
</TabsContent>
<TabsContent value="team" className="text-muted-foreground pt-2 text-sm">
Invite and manage your team.
</TabsContent>
</Tabs>
)
}bunx --bun @seamui/cli@latest add tabsNotes
- The indicator is a shared-layout
motion.span(layoutId) inside the active tab — selection change springs it to the new tab withsprings.snappy, fully interruptible. Each Tabs instance scopes its ownlayoutIdso multiple groups never fight. - Triggers reuse
buttonVariantsclasses on the composite-safe element (noButtonwrapper) so Base UI's roving arrow-key focus keeps working. - Full
role="tablist"semantics with arrow-key navigation and automatic activation; controlled viavalue/onValueChange, or uncontrolled viadefaultValue.
Press feedback, reduced motion, and haptics follow the global policy — see Motion and Haptics.