Tabs
Layered sections of content with one visible panel at a time and keyboard-accessible triggers.
Installation
The components are exported from @by/experience-system. Add the package with your package manager:
pnpm add @by/experience-systemIn this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.
Composition
Use the following composition to build tabs:
Tabs
├── TabsList
│ ├── TabsTrigger
│ └── TabsTrigger …
├── TabsContent
└── TabsContent …Each TabsTrigger value must match exactly one TabsContent value. Styling for the line list variant includes an inner label span on triggers (see data-slot="tabs-trigger-label" in API Reference).
Usage
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@by/experience-system';Tabs and the subcomponents are client pieces ('use client'). Use them inside a Client Component or a dynamic import when using the Next.js App Router.
<Tabs defaultValue="account">
<TabsList>
<TabsTrigger value="account">Account</TabsTrigger>
<TabsTrigger value="password">Password</TabsTrigger>
</TabsList>
<TabsContent value="account">Make changes to your account here.</TabsContent>
<TabsContent value="password">Change your password here.</TabsContent>
</Tabs>Examples
Overview
Default TabsList variant with Card panels (same preview as at the top of the page).
Line
Use TabsList variant="line" for a minimal list with an accent underline (horizontal) or bar (vertical) on the active trigger.
API Reference
The tables below mirror the Radix UI Tabs API. Subsection titles name the exports from @by/experience-system. The root and list forward dir from ThemeProvider when you do not pass dir yourself.
Tabs
Contains all tabs parts. Maps to Radix Tabs.Root.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
defaultValue | string | — |
value | string | — |
onValueChange | (value: string) => void | — |
orientation | horizontal | vertical | horizontal |
dir | ltr | rtl | From ThemeProvider unless overridden |
activationMode | automatic | manual | automatic |
| Data attribute | Values |
|---|---|
data-slot | tabs |
data-orientation | horizontal | vertical |
TabsList
Contains the triggers. Maps to Radix Tabs.List.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
loop | boolean | true |
variant | default | line | default (Experience System extension) |
| Data attribute | Values |
|---|---|
data-slot | tabs-list |
data-variant | default | line |
data-orientation | horizontal | vertical |
TabsTrigger
The control that activates its panel. Maps to Radix Tabs.Trigger. When TabsList uses variant="line", children are wrapped in a span with data-slot="tabs-trigger-label" for label styling.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
value | string | — (required) |
disabled | boolean | false |
| Data attribute | Values |
|---|---|
data-slot | tabs-trigger |
data-state | active | inactive |
data-disabled | Present when disabled |
data-orientation | horizontal | vertical |
TabsContent
The panel for a trigger. Maps to Radix Tabs.Content.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
value | string | — (required) |
forceMount | boolean | — |
| Data attribute | Values |
|---|---|
data-slot | tabs-content |
data-state | active | inactive |
data-orientation | horizontal | vertical |
Accessibility
Follow the Tabs WAI-ARIA pattern: triggers are in a tablist, each trigger is a tab, and each panel uses tabpanel. Use concise trigger text and ensure the selected state is clear visually (including line variant). See Radix Tabs — accessibility.
Keyboard interactions
| Key | Description |
|---|---|
Tab | Moves focus to the active trigger when entering the tablist; from a focused trigger, moves focus to the active TabsContent. |
ArrowRight | Moves focus to the next trigger (horizontal ltr); activates its content per activationMode. |
ArrowLeft | Moves focus to the previous trigger (horizontal ltr); activates its content per activationMode. |
ArrowDown | Moves focus to the next trigger when orientation is vertical; activates its content per activationMode. |
ArrowUp | Moves focus to the previous trigger when orientation is vertical; activates its content per activationMode. |
Home | Moves focus to the first trigger and activates its content. |
End | Moves focus to the last trigger and activates its content. |
In rtl horizontal layouts, ArrowLeft / ArrowRight follow the reading direction. With activationMode="manual", arrow keys move focus without changing the selected tab until Space or Enter (see Radix docs).
Source in the repo: packages/experience-system/src/components/Tabs/Tabs.tsx. Agent-oriented contracts: packages/experience-system/src/components/Tabs/Tabs.instructions.md.