Tabs

Accessible tab interface with keyboard navigation and automatic or manual activation.

Tabs

The Tabs component provides a fully accessible tabbed interface following WAI-ARIA patterns. It supports controlled and uncontrolled modes, arrow-key navigation, and both automatic (select on focus) and manual (select on click) activation modes.

Tabs requires sub-components: TabsList for the tab buttons, TabsTrigger for individual tabs, and TabsContent for panel content.


Features

  • Controlled/uncontrolled modes
  • Automatic (focus-selects) or manual (click-to-select) activation
  • Arrow-key navigation with roving tab index
  • Horizontal or vertical orientation
  • RTL support
  • Full ARIA tablist/tab/tabpanel semantics

Usage

import { Tabs, TabsList, TabsTrigger, TabsContent } from '@loke/ui/tabs';

export default function Example() {
  return (
    <Tabs defaultValue="tab1">
      <TabsList>
        <TabsTrigger value="tab1">Tab 1</TabsTrigger>
        <TabsTrigger value="tab2">Tab 2</TabsTrigger>
        <TabsTrigger value="tab3">Tab 3</TabsTrigger>
      </TabsList>
      <TabsContent value="tab1">Content for tab 1</TabsContent>
      <TabsContent value="tab2">Content for tab 2</TabsContent>
      <TabsContent value="tab3">Content for tab 3</TabsContent>
    </Tabs>
  );
}

Props

Tabs

Prop

Type

TabsList

Prop

Type

TabsTrigger

Prop

Type

TabsContent

Prop

Type


Examples

Basic tabs with active styling

Overview: A summary of key product information and highlights.

Controlled tabs

Manage your account details and preferences.

Active tab: account

Vertical orientation

General application settings and display preferences.

Basic horizontal tabs

<Tabs defaultValue="overview">
  <TabsList className="border-b">
    <TabsTrigger value="overview" className="px-4 py-2">Overview</TabsTrigger>
    <TabsTrigger value="details" className="px-4 py-2">Details</TabsTrigger>
    <TabsTrigger value="reviews" className="px-4 py-2">Reviews</TabsTrigger>
  </TabsList>
  <div className="mt-4">
    <TabsContent value="overview" className="text-sm text-gray-700">Overview panel content</TabsContent>
    <TabsContent value="details" className="text-sm text-gray-700">Details panel content</TabsContent>
    <TabsContent value="reviews" className="text-sm text-gray-700">Reviews panel content</TabsContent>
  </div>
</Tabs>

Vertical tabs

<Tabs defaultValue="settings" orientation="vertical" className="flex gap-4">
  <TabsList className="flex flex-col w-32 border-r">
    <TabsTrigger value="settings" className="justify-start px-3 py-2">Settings</TabsTrigger>
    <TabsTrigger value="security" className="justify-start px-3 py-2">Security</TabsTrigger>
    <TabsTrigger value="notifications" className="justify-start px-3 py-2">Notifications</TabsTrigger>
  </TabsList>
  <div className="flex-1">
    <TabsContent value="settings">Settings panel</TabsContent>
    <TabsContent value="security">Security panel</TabsContent>
    <TabsContent value="notifications">Notifications panel</TabsContent>
  </div>
</Tabs>

Manual activation (click to select)

<Tabs defaultValue="tab1" activationMode="manual">
  <TabsList>
    <TabsTrigger value="tab1">Tab 1</TabsTrigger>
    <TabsTrigger value="tab2">Tab 2</TabsTrigger>
  </TabsList>
  <TabsContent value="tab1">Click to select tabs (not just arrow focus)</TabsContent>
  <TabsContent value="tab2">This is tab 2</TabsContent>
</Tabs>

Keyboard Navigation

  • Arrow Left/Right (horizontal) or Arrow Up/Down (vertical): Move focus between tabs
  • Home/End: Jump to first/last tab
  • Tab: Move to next focusable element outside the tabs
  • Space/Enter (manual mode): Select the focused tab

In automatic mode, the focused tab is selected immediately. In manual mode, you must press Space/Enter to select.


Accessibility

  • TabsList has role="tablist" and aria-orientation
  • Triggers have role="tab", aria-selected, and aria-controls
  • Content panels have role="tabpanel", aria-labelledby, and tabindex="0"
  • Disabled triggers have aria-disabled="true"
  • Only one trigger is in the tab order at a time (roving tab index)

Best practices

  • Use activationMode="automatic" for quick tabs (default); use "manual" for tabs with significant content or complex state
  • Provide clear, concise tab labels
  • Don't disable tabs unless necessary; explain why if disabled
  • Keep content organized logically; avoid too many tabs (5–7 is a good limit)
  • Test keyboard navigation with screen readers to ensure tab labels and panel association is clear