Skip to main content

Tabs

StorybookView in Storybook

Explore interactive examples and all component variations in our Storybook.

The Tabs component organizes content into multiple panels with accessible keyboard navigation, focus management, and customizable sizing. Supports two visual variants — the default pill style and an outline file-tab style — as well as controlled and uncontrolled modes.

Basic Usage​

Overview content

Sizes​

Pass the same size to both TabsList and each TabsTrigger. Available sizes: sm, md (default), lg, xl.

sm

md

lg

xl

With Icons​

Place a Lucide icon before the label inside TabsTrigger. The trigger handles spacing automatically.

Public Profile

Update your photo and personal details.

Outline Variant​

Set variant="outline" on the Tabs root for a file-tab appearance — an underline connects the list to the content area, and the active tab appears raised above it. Ideal for code editors, document viewers, or any multi-panel interface that should feel like open files.

'use client'
import { cn } from '@/lib/utils'

Collapse Label​

Add collapseLabel to a TabsTrigger to show only the icon when that tab is inactive. The label reappears when the tab becomes active. This keeps the tab bar compact while still surfacing context on selection. The label remains accessible to screen readers at all times.

Overview

collapseLabel works with both variants and can be mixed — some tabs collapse while others always show their label:

Notifications panel

Controlled​

Pass value and onValueChange to control the active tab from outside:

Active:
profile
Profile panel

Properties​

Tabs​

PropertyTypeDefaultDescription
defaultValuestring—Initial active tab (uncontrolled).
valuestring—Active tab value (controlled).
onValueChange(value: string) => void—Callback fired when the active tab changes.
variant"default" | "outline""default"Visual style. default is a pill/segmented control; outline looks like file tabs.
orientation"horizontal" | "vertical""horizontal"Layout direction of the tab list.
dir"ltr" | "rtl"—Reading direction.
activationMode"automatic" | "manual""automatic"Whether focus automatically activates a tab.
classNamestring—Additional CSS classes.

TabsList​

PropertyTypeDefaultDescription
size"sm" | "md" | "lg" | "xl""md"Height of the tab list.
loopbooleantrueWhether arrow-key navigation wraps around.
classNamestring—Additional CSS classes.

TabsTrigger​

PropertyTypeDefaultDescription
valuestring—Required. Unique identifier linking this trigger to its content panel.
size"sm" | "md" | "lg" | "xl""md"Size of the trigger. Should match the TabsList size.
collapseLabelbooleanfalseWhen true, hides the text label when the tab is inactive, showing only the icon. Requires an icon as the first child. The label remains visible to screen readers.
disabledbooleanfalsePrevents selection and keyboard navigation.
classNamestring—Additional CSS classes.

TabsContent​

PropertyTypeDefaultDescription
valuestring—Required. Matches the corresponding TabsTrigger value.
forceMountbooleanfalseKeep the panel in the DOM even when inactive (useful for animating exit).
classNamestring—Additional CSS classes.

Accessibility​

  • Keyboard navigation — ←/→ (or ↑/↓ for vertical) move between tabs; Home/End jump to first/last. Focus loops by default.
  • Roving tabindex — only the active tab is in the natural tab sequence; inactive tabs are reachable via arrow keys.
  • ARIA — role="tablist", role="tab", role="tabpanel", aria-selected, aria-controls, and aria-labelledby are set automatically.
  • collapseLabel — collapsed labels use sr-only so screen readers still announce the full tab name.