Experience System
Components

Tabs

Layered sections of content with one visible panel at a time and keyboard-accessible triggers.

Overview
View your key metrics and recent project activity. Track progress across all your active projects.
You have 12 active projects and 3 pending tasks.

Installation

The components are exported from @by/experience-system. Add the package with your package manager:

pnpm add @by/experience-system

In 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).

Overview
View your key metrics and recent project activity. Track progress across all your active projects.
You have 12 active projects and 3 pending tasks.

Line

Use TabsList variant="line" for a minimal list with an accent underline (horizontal) or bar (vertical) on the active trigger.

Overview panel for the line variant. The active tab shows an accent underline (horizontal) or bar (vertical).

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.

PropTypeDefault
asChildbooleanfalse
defaultValuestring
valuestring
onValueChange(value: string) => void
orientationhorizontal | verticalhorizontal
dirltr | rtlFrom ThemeProvider unless overridden
activationModeautomatic | manualautomatic
Data attributeValues
data-slottabs
data-orientationhorizontal | vertical

TabsList

Contains the triggers. Maps to Radix Tabs.List.

PropTypeDefault
asChildbooleanfalse
loopbooleantrue
variantdefault | linedefault (Experience System extension)
Data attributeValues
data-slottabs-list
data-variantdefault | line
data-orientationhorizontal | 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.

PropTypeDefault
asChildbooleanfalse
valuestring— (required)
disabledbooleanfalse
Data attributeValues
data-slottabs-trigger
data-stateactive | inactive
data-disabledPresent when disabled
data-orientationhorizontal | vertical

TabsContent

The panel for a trigger. Maps to Radix Tabs.Content.

PropTypeDefault
asChildbooleanfalse
valuestring— (required)
forceMountboolean
Data attributeValues
data-slottabs-content
data-stateactive | inactive
data-orientationhorizontal | 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

KeyDescription
TabMoves focus to the active trigger when entering the tablist; from a focused trigger, moves focus to the active TabsContent.
ArrowRightMoves focus to the next trigger (horizontal ltr); activates its content per activationMode.
ArrowLeftMoves focus to the previous trigger (horizontal ltr); activates its content per activationMode.
ArrowDownMoves focus to the next trigger when orientation is vertical; activates its content per activationMode.
ArrowUpMoves focus to the previous trigger when orientation is vertical; activates its content per activationMode.
HomeMoves focus to the first trigger and activates its content.
EndMoves 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.