Install
Pull Tabs from the barrel for everyday use, or the granular path when you want a tighter bundle.
import { Tabs } from "@brika/clay";import { Tabs } from "@brika/clay/components/tabs";A minimal example
Drop this into a page. Native HTML attributes pass through to the underlying primitive.
'use client';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@brika/clay/components/tabs';
/** Standard tabs with a pill-style list and three content panels. */
export default function TabsDefaultDemo() {
return (
<Tabs defaultValue="overview" className="w-full max-w-md">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="activity">Activity</TabsTrigger>
<TabsTrigger value="settings">Settings</TabsTrigger>
</TabsList>
<TabsContent value="overview" className="mt-4 text-clay-default text-sm">
<p>Your project at a glance, key metrics, recent deploys, and health status.</p>
</TabsContent>
<TabsContent value="activity" className="mt-4 text-clay-default text-sm">
<p>A chronological feed of commits, reviews, and comments from the last 7 days.</p>
</TabsContent>
<TabsContent value="settings" className="mt-4 text-clay-default text-sm">
<p>Configure environment variables, access control, and notification preferences.</p>
</TabsContent>
</Tabs>
);
}Tabs, every way
Controlled
Controlled tabs, drive the active tab programmatically with `value` and `onValueChange`.
Line
Line-style variant with an underline indicator instead of a pill.
Vertical
Vertical orientation, tabs stack on the left and content fills the right.
With Badge
Badge inside a tab trigger, compose freely to show counts or status.
Accessibility
- Arrow keys navigate between triggers inside the list, Tab moves focus to the active panel.
- Active panel carries
aria-labelledbypointing to its trigger. - Triggers carry
role="tab"andaria-selected; the list carriesrole="tablist". - Vertical tabs require
orientation="vertical"so AT uses the correct arrow key direction.
Theme tokens
Every CSS variable Tabs reads, with its default and the
dotted path you'd write in a ThemeConfig JSON
to override it. Set any of these in your theme to retune Tabs
without touching component code.
Tabs tokens
24 tokens--tabs-list-containercolorvar(--muted)components.tabs.listContainerBackground of the tabs list rail in the default (pill) variant. The line variant keeps the list transparent.
--tabs-list-labelcolorvar(--muted-foreground)components.tabs.listLabelDefault label color for tabs in their inactive state. Active tabs override to `trigger-active-label`.
--tabs-trigger-active-containercolorvar(--background)components.tabs.triggerActiveContainerBackground of the active tab pill (default variant).
--tabs-trigger-active-labelcolorvar(--foreground)components.tabs.triggerActiveLabelForeground color of the active tab.
--tabs-trigger-hover-labelcolorvar(--foreground)components.tabs.triggerHoverLabelForeground color of an inactive tab on hover.
--tabs-line-indicatorcolorvar(--foreground)components.tabs.lineIndicatorColor of the underline rule painted under the active tab in the line variant.
--tabs-trigger-focus-bordercolorvar(--ring)components.tabs.triggerFocusBorderBorder color drawn on a tab trigger on `focus-visible`. Pairs with `trigger-focus-ring` to render the keyboard focus halo.
--tabs-trigger-focus-outlinecolorvar(--ring)components.tabs.triggerFocusOutlineOutline color drawn on a tab trigger on `focus-visible`. Sits underneath the focus ring at 1px width.
--tabs-trigger-focus-ringcolorvar(--ring)components.tabs.triggerFocusRingColor of the 3px focus halo painted around a tab trigger on `focus-visible`. Rendered at 50% opacity to soften the outer glow.
--tabs-trigger-active-border-darkcolorvar(--input)components.tabs.triggerActiveBorderDarkBorder color of the active tab pill in dark mode (default variant). Light mode keeps the transparent resting border so only the pill background reads as active.
--tabs-trigger-padding-xsizecalc(var(--spacing) * 3)components.tabs.triggerPaddingXInline padding inside a tab trigger.
--tabs-trigger-padding-ysizecalc(var(--spacing) * 1.5)components.tabs.triggerPaddingYBlock padding inside a tab trigger.
--tabs-radiusradiusvar(--radius-control)components.tabs.radiusTabs corner radius.
--tabs-border-widthborder-width1pxcomponents.tabs.borderWidthBorder width on the tabs. Set non-zero for outline-style variants.
--tabs-border-styleborder-stylesolidcomponents.tabs.borderStyleBorder style on the tabs (`solid`, `dashed`, `double`, `none`).
--tabs-font-familyfont-familyvar(--font-sans)components.tabs.fontFamilyTypeface for tabs.
--tabs-font-sizefont-sizevar(--text-label-lg)components.tabs.fontSizeFont size for tabs.
--tabs-font-weightfont-weight500components.tabs.fontWeightFont weight for tabs.
--tabs-line-heightline-height1.25components.tabs.lineHeightLine height for tabs.
--tabs-letter-spacingletter-spacing0components.tabs.letterSpacingLetter spacing for tabs. Useful for caps labels.
--tabs-text-transformtext-transformnonecomponents.tabs.textTransformText transform for tabs (`uppercase`, `lowercase`, `capitalize`, `none`).
--tabs-backdrop-blurblur0pxcomponents.tabs.backdropBlurBackdrop blur applied to the tab pill bar. Set non-zero (with a translucent muted color) for a frosted-glass tab strip.
--tabs-durationdurationvar(--motion-standard-duration)components.tabs.durationTransition duration for tabs state changes.
--tabs-easingeasingvar(--motion-standard-easing)components.tabs.easingTransition easing for tabs state changes.
Override in a theme
Authoring a theme is plain JSON. Drop overrides under
components.tabs, the names
are camelCase versions of the variable suffix.
{
"id": "my-theme",
"name": "My Theme",
"description": "...",
"accentSwatches": ["#000"],
"components": {
"tabs": {
"radius": "var(--radius-control)"
}
}
}
Then apply with applyTheme(myTheme)
(see the theming guide),
scope it to a subtree with themeToCssVars(myTheme, mode),
or consume any token directly in your own JSX with the matching Tailwind utility
(e.g. bg-tabs-…) — see the
chips on each token row.
API reference
Props specific to Tabs. Native HTML attributes pass through to the underlying primitive, see the component source on GitHub for the full type signature.
<Tabs />
passthroughNo wrapper-specific props, all attributes pass through to the underlying primitive.
<TabsContent />
passthroughNo wrapper-specific props, all attributes pass through to the underlying primitive.
<TabsList />
1 prop- variantdefault
'default''default' | 'line'"default" pill-style or "line" underline-style.
<TabsTrigger />
passthroughNo wrapper-specific props, all attributes pass through to the underlying primitive.