Tabs
Tabs switch between related panels without leaving the current product context.
Overview and decision boundary
Use Tabs to switch between related panels within the same context.
Do not use Tabs for unrelated page destinations or a form selection value.
import { ArrowRight, LayoutDashboard } from "@nerio-ui/adapters/icons";import { Badge } from "@nerio-ui/ui";import { Tabs, TabsContent, TabsIndicator, TabsList, TabsPanels, TabsTrigger } from "@nerio-ui/ui/client";<Tabs defaultValue="overview" variant="segmented" size="md"> <TabsList aria-label="Workspace sections"> <TabsTrigger value="overview" leadingIcon={LayoutDashboard} badge={<Badge size="sm">12</Badge>}>Overview</TabsTrigger> <TabsTrigger value="activity" trailingIcon={ArrowRight}>Activity</TabsTrigger> <TabsIndicator /> </TabsList> <TabsPanels> <TabsContent value="overview">Overview content</TabsContent> <TabsContent value="activity">Activity content</TabsContent> </TabsPanels></Tabs>Installation and imports
Install the editable registry source, or use the matching package entrypoint when the product keeps Nerio as a workspace dependency.
pnpm dlx nerio add tabsimport { Badge } from "@nerio-ui/ui";import { Tabs, TabsContent, TabsIndicator, TabsList, TabsPanels, TabsTrigger } from "@nerio-ui/ui/client";Usage
import { Badge } from "@nerio-ui/ui";import { Tabs, TabsContent, TabsIndicator, TabsList, TabsPanels, TabsTrigger } from "@nerio-ui/ui/client";<Tabs defaultValue="overview" variant="segmented"> <TabsList aria-label="Workspace sections"> <TabsTrigger value="overview" badge={<Badge size="sm">12</Badge>}>Overview</TabsTrigger> <TabsTrigger value="activity">Activity</TabsTrigger> <TabsIndicator /> </TabsList> <TabsPanels> <TabsContent value="overview">Overview content</TabsContent> <TabsContent value="activity">Activity content</TabsContent> </TabsPanels></Tabs>Variants
<Tabs defaultValue="overview" variant="bordered">...</Tabs><Tabs defaultValue="overview" variant="separate">...</Tabs><Tabs defaultValue="overview" variant="segmented">...</Tabs><Tabs size="sm">...</Tabs><Tabs size="md">...</Tabs><Tabs size="lg">...</Tabs><TabsList layout="fill" aria-label="Equal workspace views">...</TabsList><Tabs orientation="vertical">...</Tabs><TabsList scrollable aria-label="Narrow project sections">...</TabsList><Tabs value={value} onValueChange={(nextValue, details) => { setValue(nextValue); setDirection(details.activationDirection); setReason(details.reason); }}>...</Tabs>| Variant | Use |
|---|---|
bordered | Quiet default with an edge accent indicator. |
separate | Independent compact triggers. |
segmented | A compact shared control surface. |
Anatomy
<TabsTrigger leadingIcon={LayoutDashboard} badge={<Badge size="sm">12</Badge>} value="overview">Overview</TabsTrigger>| Slot | Purpose |
|---|---|
root | Base UI root with size, variant, and orientation. |
list | Named controls with content or fill layout. |
trigger | Visible label with optional icons and Badge. |
indicator | Base UI positioned selected treatment. |
panels / content | Transition-safe panel association. |
States
<TabsList activateOnFocus aria-label="Immediate panels">...</TabsList><div dir="rtl"><Tabs>...</Tabs></div>| State | Behavior |
|---|---|
Default / active | The indicator follows Base UI active-tab CSS variables. |
Focus-visible | Inset focus treatment remains visible inside a scrollable list. |
Disabled | Disabled tabs are visually muted and skipped by keyboard navigation. |
Scrollable | Horizontal lists scroll without wrapping labels. |
Reduced motion | Indicator and panel transitions become immediate. |
RTL | The horizontal indicator follows physical active-tab geometry in either direction. |
Motion
- State changes should use shared motion tokens and preserve reduced-motion behavior.
Accessibility
- Uses the Base UI Tabs primitive.
- Uses Base UI tab, tablist, and tabpanel relationships and selected state; Nerio keeps keyboard focus on enabled tabs.
- Provide aria-label or aria-labelledby when the tablist purpose is not clear from adjacent labelled content.
- Every trigger requires a visible text label; decorative icons are hidden from assistive technology and Badge text remains available.
- Manual activation is the default. Use activateOnFocus only when panels are available without noticeable latency.
- Provide an enabled defaultValue for predictable SSR when the first trigger is disabled.
API
| Prop | Use |
|---|---|
variant / size | bordered, separate, segmented; sm, md, lg. |
layout / scrollable | content or fill, with horizontal overflow enabled by default. |
TabsList activateOnFocus | Opt in only when panels appear without noticeable latency. |
onValueChange | Receives Base UI value and complete event details including activation direction. |
Implementation contract
Tabs preserves Base UI tab, tablist, and tabpanel relationships. Use an explicit enabled defaultValue for predictable SSR when the first trigger is disabled.
Styling contract
| Contract | Value |
|---|---|
Authoring | Complete, statically detectable Tailwind CSS v4 recipes own component visuals. |
Values | Semantic and component --n-* variables remain the canonical customization layer. |
Overrides | Customizable slots merge consumer className values with tailwindCn so conflicting utilities resolve deterministically. |
Residual CSS | Only shared keyframes and scoped no-Preflight compatibility rules remain; there is no parallel visual selector layer. |
Design notes
- Use Tabs to switch between related panels within the same context.
Do / do not
Do
Use a small set of concise peer panels and keep the selected tab visible in scrollable lists.
Do not
Use Tabs for global destinations, form values, icon-only labels, deep nesting, or slow automatic activation.
Related components
Tokens
These are the primary customization points. Override semantic or component tokens instead of changing component source.
| Token | Purpose |
|---|---|
--n-tabs-gap | Public customization point for this component contract. |
--n-tabs-content-gap | Public customization point for this component contract. |
--n-tabs-trigger-height-sm | Public customization point for this component contract. |
--n-tabs-trigger-height-md | Public customization point for this component contract. |
--n-tabs-trigger-height-lg | Public customization point for this component contract. |
--n-tabs-trigger-padding-inline-sm | Public customization point for this component contract. |
--n-tabs-trigger-padding-inline-md | Public customization point for this component contract. |
--n-tabs-trigger-padding-inline-lg | Public customization point for this component contract. |
--n-tabs-list-gap | Public customization point for this component contract. |
--n-tabs-trigger-content-gap-sm | Public customization point for this component contract. |
--n-tabs-trigger-content-gap-md | Public customization point for this component contract. |
--n-tabs-trigger-content-gap-lg | Public customization point for this component contract. |
--n-tabs-trigger-font-size-sm | Public customization point for this component contract. |
--n-tabs-trigger-font-size-md | Public customization point for this component contract. |
--n-tabs-trigger-font-size-lg | Public customization point for this component contract. |
--n-tabs-icon-size-sm | Public customization point for this component contract. |
--n-tabs-icon-size-md | Public customization point for this component contract. |
--n-tabs-icon-size-lg | Public customization point for this component contract. |
--n-tabs-radius | Public customization point for this component contract. |
--n-tabs-list-background | Public customization point for this component contract. |
--n-tabs-list-radius | Public customization point for this component contract. |
--n-tabs-list-padding | Public customization point for this component contract. |
--n-tabs-segmented-indicator-radius | Public customization point for this component contract. |
--n-tabs-foreground | Public customization point for this component contract. |
--n-tabs-foreground-hover | Public customization point for this component contract. |
--n-tabs-foreground-active | Public customization point for this component contract. |
--n-tabs-foreground-disabled | Public customization point for this component contract. |
--n-tabs-indicator-background | Public customization point for this component contract. |
--n-tabs-indicator-border-color | Public customization point for this component contract. |
--n-tabs-indicator-shadow | Public customization point for this component contract. |
--n-tabs-divider-color | Public customization point for this component contract. |
--n-tabs-accent-color | Public customization point for this component contract. |
--n-tabs-indicator-thickness | Public customization point for this component contract. |
--n-tabs-indicator-duration | Public customization point for this component contract. |
--n-tabs-indicator-easing | Public customization point for this component contract. |
--n-tabs-content-duration | Public customization point for this component contract. |
--n-tabs-content-easing | Public customization point for this component contract. |
--n-tabs-content-translate | Public customization point for this component contract. |
--n-motion-hover-duration | Public customization point for this component contract. |
--n-motion-hover-easing | Public customization point for this component contract. |
--n-focus-ring | Public customization point for this component contract. |