Tabs
A set of layered sections of content—known as tab panels—that are displayed one at a time. Perfect for organizing complex interfaces in React applications with Next.js, TypeScript, and Tailwind CSS.
You know how some interfaces have so much content that showing everything at once would be overwhelming? Tabs let users focus on one section while keeping other options visible and accessible, like file tabs in your code editor or browser tabs you probably have too many of right now.
Basic form tabs
Account and password settings organized cleanly:
Simple two-tab layout with forms inside cards. This free open source React component handles all the keyboard navigation and ARIA attributes so screen readers understand the tab structure.
npx shadcn@latest add tabs
Why tabs improve user experience
Tabs solve real interface problems:
- Reduced cognitive load - Users see one focused section at a time
- Clear navigation - All options visible without scrolling
- Contextual grouping - Related content stays together
- Space efficiency - Multiple panels in the same area
- State preservation - Content persists when switching tabs
- Familiar pattern - Users already know how tabs work
Common tab patterns
Vertical sidebar navigation
Settings panel with icon navigation:
Underline style with badges
Modern navigation with indicators:
These examples show tabs in real scenarios - settings panels, dashboards, navigation bars. Each pattern serves different interface needs while maintaining consistent interaction patterns.
Perfect for content organization
Tabs work best when you have distinct content sections that users don't need to see simultaneously. Settings screens, multi-step forms, dashboard views, documentation sections, profile pages. Much cleaner than accordion or long scrolling pages when content is truly separate.
Built on Radix UI Tabs primitive. Full TypeScript support. Styled with Tailwind CSS to match the shadcn design system.
API Reference
Tabs
The root container that holds all tab components.
Prop | Type | Default | Description |
---|---|---|---|
defaultValue | string | - | The value of the tab that should be active when initially rendered (uncontrolled) |
value | string | - | The controlled value of the tab to activate |
onValueChange | (value: string) => void | - | Event handler called when the active tab changes |
orientation | "horizontal" | "vertical" | "horizontal" | The orientation of the tabs |
dir | "ltr" | "rtl" | "ltr" | Reading direction of the tabs |
activationMode | "automatic" | "manual" | "automatic" | Whether tabs are activated on focus or require clicking |
className | string | - | Additional CSS classes |
TabsList
Container for the tab triggers.
Prop | Type | Default | Description |
---|---|---|---|
loop | boolean | true | When true, keyboard navigation will loop from last to first and vice versa |
className | string | - | Additional CSS classes |
TabsTrigger
The button that activates its associated content panel.
Prop | Type | Default | Description |
---|---|---|---|
value | string | - | A unique value that associates the trigger with a content panel |
disabled | boolean | false | When true, prevents the user from interacting with the tab |
className | string | - | Additional CSS classes |
TabsContent
The content panel associated with a trigger.
Prop | Type | Default | Description |
---|---|---|---|
value | string | - | The value that associates the content with a trigger |
forceMount | boolean | - | Used to force mounting when more control is needed |
className | string | - | Additional CSS classes |
Data Attributes
Components automatically apply data attributes for styling:
Component | Attribute | Values | Description |
---|---|---|---|
All | [data-orientation] | "horizontal" | "vertical" | The orientation |
TabsTrigger | [data-state] | "active" | "inactive" | Whether the tab is selected |
TabsTrigger | [data-disabled] | Present when disabled | Applied when disabled |
TabsContent | [data-state] | "active" | "inactive" | Whether the content is visible |
Keyboard Navigation
Full keyboard support for accessibility:
Key | Description |
---|---|
Tab | When focus moves to tabs, focuses the active trigger. When a trigger is focused, moves focus to active content |
Arrow Down | Moves focus to next trigger (vertical orientation) and activates it |
Arrow Right | Moves focus to next trigger (horizontal orientation) and activates it |
Arrow Up | Moves focus to previous trigger (vertical orientation) and activates it |
Arrow Left | Moves focus to previous trigger (horizontal orientation) and activates it |
Home | Moves focus to first trigger and activates it |
End | Moves focus to last trigger and activates it |
Activation Modes
Tabs support two activation modes:
- Automatic (default) - Panel changes when tab receives focus via keyboard navigation
- Manual - Panel only changes when clicked or activated with Enter/Space keys
Controlled vs Uncontrolled
Tabs can manage their own state (uncontrolled) or be controlled by parent component state. The examples above demonstrate both patterns - check the preview code to see state management implementations.
Common patterns
The examples above demonstrate various tab patterns including:
- Icons and text - Clear visual indicators with descriptive labels
- Badges and indicators - Show counts or status information
- Full-width layouts - Evenly distributed tab triggers
- Underline styling - Modern border-based visual design
- Vertical orientation - Sidebar-style navigation for settings
- Grouped sections - Organized with separators and logical grouping
Check the preview examples above to see these patterns in action with full interactivity.
Accessibility Features
Built-in accessibility support includes:
- ARIA pattern - Follows WAI-ARIA tabs design pattern
- Keyboard navigation - Full keyboard support with arrow keys
- Focus management - Proper focus handling and indicators
- Screen reader support - Semantic HTML and ARIA attributes
- Roving tabindex - Only active tab is in tab sequence
- Orientation awareness - Arrow keys adapt to orientation
- Loop navigation - Optional wraparound at list ends
Design tips for better tabs
Keep these principles in mind when using tabs:
- Label clearly - Tab labels should be short and descriptive
- Logical order - Arrange tabs by importance or workflow
- Visual feedback - Active tab should be clearly distinguished
- Consistent height - Keep tab panels similar height to avoid jumps
- Mobile consideration - Test horizontal scrolling on small screens
- Icon usage - Icons can help but shouldn't replace text labels
- Loading states - Show loading in panels, not on triggers
- Deep linking - Consider URL updates for shareable tab states
- Keyboard users - Test navigation without mouse
- Content persistence - Maintain form state when switching tabs
Table
A responsive table component for displaying tabular data. Perfect for dashboards, admin panels, and data management in React applications with Next.js, TypeScript, and Tailwind CSS.
Textarea
Captures multi-line user input for forms, comments, and longer text content. Perfect for feedback forms and messaging in React applications with Next.js, TypeScript, and Tailwind CSS.