Skip to content

Tabs

<Tabs> rotates between sibling sub-views inside one page — Overview / Activity / Settings on a detail page, for example. Each tab owns a panel; only the active one renders.

import from "@na/ui/components/tabs" ▶ Open in Storybook packages/ui/src/components/tabs.tsx

When to use

  • Detail pages with 2–5 logically-related sub-views.
  • Settings sub-pages where switching is fast and stateless.

Don’t use Tabs for: navigation between top-level pages (URL change → real <a> links), step-driven flows (Stepper — planned), or 6+ choices (collapse with RightPanel or split into separate pages).

Default

Overview body content goes here.
<Tabs defaultValue="overview">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="activity">Activity</TabsTrigger>
<TabsTrigger value="settings">Settings</TabsTrigger>
</TabsList>
<TabsContent value="overview"></TabsContent>
<TabsContent value="activity"></TabsContent>
<TabsContent value="settings"></TabsContent>
</Tabs>

Disabled tab

You see this. The other tab is disabled.
<TabsTrigger value="audit" disabled>Audit (admin only)</TabsTrigger>

API

Tabs

Prop Type Default Description
value string Controlled active tab. Pair with onValueChange.
defaultValue string Initial active tab for uncontrolled mode.
onValueChange (value: string) => void Fires on tab change.
orientation "horizontal" | "vertical" "horizontal" Drives arrow-key navigation direction.
activationMode "automatic" | "manual" "automatic" automatic = arrow keys also activate. manual = arrow moves focus only; Enter activates.

TabsList / TabsTrigger / TabsContent

TabsTrigger requires value. TabsContent requires the matching value.

Design guidelines

✓ Do

  • Persist the active tab to the URL when reload-survival matters (e.g., ?tab=activity).
  • Lazy-mount expensive panels — content for inactive tabs need not render eagerly.
  • Order tabs by the user's frequency of use, left to right.

✗ Don't

  • Use Tabs as page-level navigation. Tabs are sub-views; navigation belongs in URL.
  • Hide critical state behind a tab. Anything the user might miss should be on the default tab.
  • Add 6+ tabs. The TabsList overflows ungracefully; reach for a layout with a sidebar.

Accessibility

  • Composes Radix Tabs — role="tablist", tab items, tabpanel content. Arrow keys move between tabs; Enter / Space activates in manual mode.
  • Each TabsContent is automatically aria-labelledby its corresponding trigger.

▶ Open Tabs stories in Storybook