Manage your account settings.
import { Tabs, TabsList, TabsTab, TabsPanel } from "@registry/components/ui/tabs";
export function TabsExample() {
return (
<div className="flex flex-col items-start justify-center">
<Tabs defaultValue="account" className="w-full max-w-72">
<TabsList>
<TabsTab value="account">Account</TabsTab>
<TabsTab value="password">Password</TabsTab>
<TabsTab value="settings">Settings</TabsTab>
</TabsList>
<TabsPanel value="account">
<p className={tabContentClassName}>Manage your account settings.</p>
</TabsPanel>
<TabsPanel value="password">
<p className={tabContentClassName}>Change your password.</p>
</TabsPanel>
<TabsPanel value="settings">
<p className={tabContentClassName}>Configure application settings.</p>
</TabsPanel>
</Tabs>
</div>
);
} Examples
Underline variant
Use the underline variant for a minimal, border-based indicator style.
View your project overview and key metrics.
import { Tabs, TabsList, TabsTab, TabsPanel } from "@registry/components/ui/tabs";
export function TabsUnderlineExample() {
return (
<div className="flex flex-col items-start justify-center">
<Tabs defaultValue="overview" className="w-full max-w-72">
<TabsList variant="underline">
<TabsTab value="overview">Overview</TabsTab>
<TabsTab value="analytics">Analytics</TabsTab>
<TabsTab value="reports">Reports</TabsTab>
</TabsList>
<TabsPanel value="overview">
<p className={tabContentClassName}>View your project overview and key metrics.</p>
</TabsPanel>
<TabsPanel value="analytics">
<p className={tabContentClassName}>Dive into detailed analytics and trends.</p>
</TabsPanel>
<TabsPanel value="reports">
<p className={tabContentClassName}>Generate and download custom reports.</p>
</TabsPanel>
</Tabs>
</div>
);
} Sizes
Available sizes: default, sm, lg.
Small size tabs.
Default size tabs.
Large size tabs.
import { Tabs, TabsList, TabsTab, TabsPanel } from "@registry/components/ui/tabs";
export function TabsSizesExample() {
return (
<div className="flex flex-col items-start gap-6">
<Tabs defaultValue="sm" className="w-full max-w-72">
<TabsList size="sm">
<TabsTab value="sm">Small</TabsTab>
<TabsTab value="sm2">Tab 2</TabsTab>
</TabsList>
<TabsPanel value="sm">
<p className={tabContentClassName}>Small size tabs.</p>
</TabsPanel>
<TabsPanel value="sm2">
<p className={tabContentClassName}>Another small tab.</p>
</TabsPanel>
</Tabs>
<Tabs defaultValue="default" className="w-full max-w-72">
<TabsList size="default">
<TabsTab value="default">Default</TabsTab>
<TabsTab value="default2">Tab 2</TabsTab>
</TabsList>
<TabsPanel value="default">
<p className={tabContentClassName}>Default size tabs.</p>
</TabsPanel>
<TabsPanel value="default2">
<p className={tabContentClassName}>Another default tab.</p>
</TabsPanel>
</Tabs>
<Tabs defaultValue="lg" className="w-full max-w-72">
<TabsList size="lg">
<TabsTab value="lg">Large</TabsTab>
<TabsTab value="lg2">Tab 2</TabsTab>
</TabsList>
<TabsPanel value="lg">
<p className={tabContentClassName}>Large size tabs.</p>
</TabsPanel>
<TabsPanel value="lg2">
<p className={tabContentClassName}>Another large tab.</p>
</TabsPanel>
</Tabs>
</div>
);
} Vertical orientation
Set orientation="vertical" on Tabs to arrange tabs and panels side by side.
General settings for your application.
import { Tabs, TabsList, TabsTab, TabsPanel } from "@registry/components/ui/tabs";
export function TabsVerticalExample() {
return (
<div className="flex flex-col items-start justify-center">
<Tabs defaultValue="general" orientation="vertical" className="w-full max-w-72">
<TabsList>
<TabsTab value="general">General</TabsTab>
<TabsTab value="display">Display</TabsTab>
<TabsTab value="advanced">Advanced</TabsTab>
</TabsList>
<TabsPanel value="general">
<p className={tabContentClassName}>General settings for your application.</p>
</TabsPanel>
<TabsPanel value="display">
<p className={tabContentClassName}>Customize display and appearance options.</p>
</TabsPanel>
<TabsPanel value="advanced">
<p className={tabContentClassName}>Advanced configuration and experimental features.</p>
</TabsPanel>
</Tabs>
</div>
);
} Installation
Copy the source code below into your project:
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
import { cn } from "@registry/lib/utils";
import { cva } from "class-variance-authority";
import type { VariantProps } from "class-variance-authority";
import { createContext, useContext } from "react";
type TabsVariant = "default" | "underline";
type TabsSize = "default" | "sm" | "lg";
const TabsSizeContext = createContext<TabsSize>("default");
const tabsListVariants = cva(
"relative z-0 flex items-center gap-x-0.5 data-[orientation=vertical]:h-fit data-[orientation=vertical]:flex-col data-[orientation=vertical]:gap-y-0.5",
{
compoundVariants: [
{ size: "sm", variant: "default", className: "p-1" },
{ size: "default", variant: "default", className: "p-1.5" },
{ size: "lg", variant: "default", className: "p-2" },
{
size: "sm",
variant: "underline",
className: "data-[orientation=horizontal]:py-0.5 data-[orientation=vertical]:px-0.5",
},
{
size: "default",
variant: "underline",
className: "data-[orientation=horizontal]:py-1 data-[orientation=vertical]:px-1",
},
{
size: "lg",
variant: "underline",
className: "data-[orientation=horizontal]:py-1.5 data-[orientation=vertical]:px-1.5",
},
],
defaultVariants: {
size: "default",
variant: "default",
},
variants: {
size: {
sm: "",
default: "",
lg: "",
},
variant: {
default: "w-fit justify-center rounded-lg bg-muted",
underline:
"border-border data-[orientation=horizontal]:border-b data-[orientation=vertical]:border-l *:data-[slot=tabs-trigger]:hover:bg-muted",
},
},
},
);
const tabIndicatorVariants = cva(
"absolute transition-[width,height,translate] duration-200 ease-in-out data-[orientation=horizontal]:bottom-0 data-[orientation=horizontal]:left-0 data-[orientation=horizontal]:h-(--active-tab-height) data-[orientation=horizontal]:w-(--active-tab-width) data-[orientation=horizontal]:translate-x-(--active-tab-left) data-[orientation=horizontal]:-translate-y-(--active-tab-bottom) data-[orientation=vertical]:top-0 data-[orientation=vertical]:left-0 data-[orientation=vertical]:h-(--active-tab-height) data-[orientation=vertical]:w-(--active-tab-width) data-[orientation=vertical]:translate-x-(--active-tab-left) data-[orientation=vertical]:translate-y-(--active-tab-top)",
{
compoundVariants: [
{
size: "sm",
variant: "underline",
className: "data-[orientation=horizontal]:h-px data-[orientation=vertical]:w-px",
},
{
size: "default",
variant: "underline",
className: "data-[orientation=horizontal]:h-0.5 data-[orientation=vertical]:w-0.5",
},
{
size: "lg",
variant: "underline",
className: "data-[orientation=horizontal]:h-1 data-[orientation=vertical]:w-1",
},
],
defaultVariants: {
size: "default",
variant: "default",
},
variants: {
size: {
default: "",
lg: "",
sm: "",
},
variant: {
default: "-z-1 rounded-md bg-popover",
underline:
"z-10 bg-accent data-[orientation=horizontal]:translate-y-px data-[orientation=vertical]:-translate-x-px",
},
},
},
);
const tabsTabVariants = cva(
"flex shrink-0 cursor-pointer items-center justify-center rounded-md font-medium whitespace-nowrap text-muted-foreground transition-[color,background-color,box-shadow] outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring data-active:text-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-[orientation=vertical]:w-full data-[orientation=vertical]:justify-start [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
defaultVariants: {
size: "default",
},
variants: {
size: {
default: "gap-1.5 px-2 py-1.5 text-sm",
lg: "gap-2 px-3 py-2 text-base",
sm: "gap-1 px-1.5 py-1.5 text-xs",
},
},
},
);
function Tabs({ className, ...props }: BaseTabs.Root.Props) {
return (
<BaseTabs.Root
className={cn("flex flex-col gap-6 data-[orientation=vertical]:flex-row", className)}
data-slot="tabs"
{...props}
/>
);
}
function TabsList({
variant = "default",
size = "default",
className,
children,
...props
}: BaseTabs.List.Props & {
variant?: TabsVariant;
size?: TabsSize;
}) {
return (
<BaseTabs.List
className={cn(tabsListVariants({ className, size, variant }))}
data-slot="tabs-list"
{...props}
>
<TabsSizeContext.Provider value={size}>
{children}
<BaseTabs.Indicator
className={cn(tabIndicatorVariants({ size, variant }))}
data-slot="tab-indicator"
/>
</TabsSizeContext.Provider>
</BaseTabs.List>
);
}
type TabsTabProps = BaseTabs.Tab.Props & VariantProps<typeof tabsTabVariants>;
function TabsTab({ className, size, ...props }: TabsTabProps) {
const inheritedSize = useContext(TabsSizeContext);
return (
<BaseTabs.Tab
className={cn(tabsTabVariants({ className, size: size ?? inheritedSize }))}
data-slot="tabs-trigger"
{...props}
/>
);
}
function TabsPanel({ className, ...props }: BaseTabs.Panel.Props) {
return (
<BaseTabs.Panel
className={cn("flex flex-1 flex-col gap-6 outline-none", className)}
data-slot="tabs-content"
{...props}
/>
);
}
export { Tabs, TabsList, TabsTab, TabsTab as TabsTrigger, TabsPanel, TabsPanel as TabsContent }; API Reference
Tabs
This component does not add any props on top of Base UI Tabs.Root . See the Base UI docs for the full API reference.
TabsList
The TabsList component extends the Base UI Tabs.List
props and adds the following:
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "underline" | "default" | Visual style of the tabs list. |
| size | "default" | "sm" | "lg" | "default" | Size of the tabs and indicator. |
TabsTab
The TabsTab component extends the Base UI Tabs.Tab
props and adds the following:
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "default" | "sm" | "lg" | — | Override the tab size. Inherits from TabsList by default. |
TabsPanel
This component does not add any props on top of Base UI Tabs.Panel . See the Base UI docs for the full API reference.