v0.5.1

Tabs

Tab navigation for switching between content panels, in underline and pill variants, built on Radix UI.

Account settings

Installation

npx paubha@latest add tabs

Usage

import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";

<Tabs defaultValue="account">
  <TabsList aria-label="Settings">
    <TabsTrigger value="account">Account</TabsTrigger>
    <TabsTrigger value="billing">Billing</TabsTrigger>
  </TabsList>
  <TabsContent value="account">Account settings</TabsContent>
  <TabsContent value="billing">Billing settings</TabsContent>
</Tabs>

The underline variant renders a 2px bottom border on every trigger (transparent when inactive, border-brand when active) rather than only on the selected one. That keeps the tab bar's height constant when selection changes, instead of jumping by 2px the way a literal reading of the static mockup would.

Examples

Pill variant

Keep labels to one or two words, and use a single tab group per set of panels — don't nest tab groups inside a panel.

With icons

An optional leading Lucide icon is sized to 16px automatically. Mark it aria-hidden so the label stays the accessible name.

Manual activation

Arrow keys select the focused tab by default. When a panel takes noticeable time to render, pass activationMode="manual" to Tabs: arrows then only move focus, and Enter or Space selects.

<Tabs defaultValue="overview" activationMode="manual">…</Tabs>

API reference

Tabs and TabsContent are direct re-exports of Radix's Root/Content.

TabsList

PropTypeDefaultDescription
variant"underline" | "pill""underline"Shared with child TabsTrigger elements via context.

Accessibility

Accessibility

  • Roles. role="tablist", each tab role="tab", each panel role="tabpanel".

  • Keyboard. Left/Right Arrow move between tabs and, by default, select the newly focused tab; Home/End jump to the first/last enabled tab. Roving tabindex keeps only the selected tab in the Tab sequence, so the next Tab moves into the panel. With activationMode="manual", arrows only move focus and Enter/Space select.

  • Label. Give TabsList an aria-label or aria-labelledby.

  • Motion. State changes use a 100ms ease-out transition, instant under prefers-reduced-motion.

  • ARIA. aria-selected on the active tab, aria-controls linking each tab to its panel, and aria-labelledby linking each panel back to its tab.