Skip to main content

Overview

Overview
Analytics
Reports
Settings
Underline variant
All
Active
Archived
Pill variant
Tabs allow users to switch between related views without navigating away from the page. They support two visual styles, optional icons, and disabled states.

Installation

npm install @araf-ds/core

Usage

import { Tabs, TabsContent, TabsList, TabsTrigger } from "@araf-ds/core"

export default function Example() {
  return (
    <Tabs defaultValue="overview">
      <TabsList>
        <TabsTrigger value="overview">Overview</TabsTrigger>
        <TabsTrigger value="analytics">Analytics</TabsTrigger>
        <TabsTrigger value="reports">Reports</TabsTrigger>
      </TabsList>
      <TabsContent value="overview">Overview content here.</TabsContent>
      <TabsContent value="analytics">Analytics content here.</TabsContent>
      <TabsContent value="reports">Reports content here.</TabsContent>
    </Tabs>
  )
}

Variants

Underline (Default)

The minimal style with a bottom border indicator. Best for page-level navigation.
Overview
Analytics
Reports
Settings
<Tabs defaultValue="overview">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="analytics">Analytics</TabsTrigger>
    <TabsTrigger value="reports">Reports</TabsTrigger>
    <TabsTrigger value="settings" disabled>Settings</TabsTrigger>
  </TabsList>
  <TabsContent value="overview">Overview content here.</TabsContent>
  <TabsContent value="analytics">Analytics content here.</TabsContent>
  <TabsContent value="reports">Reports content here.</TabsContent>
</Tabs>

Pill Style

A filled, pill-shaped active indicator. Best for filtering or segmented control contexts.
All
Active
Archived
<Tabs defaultValue="all" variant="pill">
  <TabsList>
    <TabsTrigger value="all">All</TabsTrigger>
    <TabsTrigger value="active">Active</TabsTrigger>
    <TabsTrigger value="archived">Archived</TabsTrigger>
  </TabsList>
  <TabsContent value="all">All items</TabsContent>
  <TabsContent value="active">Active items</TabsContent>
  <TabsContent value="archived">Archived items</TabsContent>
</Tabs>

With Icons

Profile
Security
Billing
<Tabs defaultValue="profile">
  <TabsList>
    <TabsTrigger value="profile" icon={<UserIcon size={16} />}>Profile</TabsTrigger>
    <TabsTrigger value="security" icon={<ShieldIcon size={16} />}>Security</TabsTrigger>
    <TabsTrigger value="billing" icon={<CreditCardIcon size={16} />}>Billing</TabsTrigger>
  </TabsList>
</Tabs>

API Reference

Tabs (Root)

value
string
Controlled active tab value.
onValueChange
(value: string) => void
Callback fired when the active tab changes.
defaultValue
string
Uncontrolled default active tab.
variant
string
default:"underline"
Visual style. Values: underline · pill
orientation
string
default:"horizontal"
Layout direction. Values: horizontal · vertical

TabsTrigger

value
string
Tab identifier (required). Must match the corresponding TabsContent value.
disabled
boolean
default:"false"
Disables this tab.
icon
ReactNode
Optional leading icon element.

TabsContent

value
string
Matches the corresponding TabsTrigger value (required).

Accessibility

  • Tabs follow the ARIA Tabs pattern with role="tablist", role="tab", and role="tabpanel"
  • Arrow keys move focus between tabs within the TabsList
  • Enter/Space activates the focused tab
  • Active tab has aria-selected="true"
  • Disabled tabs have aria-disabled="true" and are skipped by keyboard navigation
  • Each TabsContent is linked to its trigger via aria-labelledby

Do’s & Don’ts

Do

  • Use Tabs to organize related views on the same page
  • Limit to 2–7 tabs — more becomes hard to scan
  • Use underline for page-level navigation, pill for local filtering
  • Add icons to improve scannability for settings or profile tabs

Don't

  • Don’t use Tabs for navigation between separate pages — use links
  • Don’t use Tabs for sequential workflows — use a Stepper instead
  • Don’t mix underline and pill styles on the same page
  • Don’t put too much content inside a single tab panel — consider separate pages