# Tabs
URL: /design/components/tabs

A tabs component for organizing content into switchable panels.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

\[interactive preview omitted]

## Installation

With the style-aware registry configured in components.json ("@assistant-ui": "https\://r.assistant-ui.com/styles/{style}/{name}.json"), the flavor resolves from the project style automatically:

```bash
npx shadcn@latest add @assistant-ui/tabs
```

Or add by direct URL without registry configuration:

```bash
npx shadcn@latest add https://r.assistant-ui.com/base/tabs.json
```

Or install manually:

```bash
npm install @base-ui/react class-variance-authority
```

Then copy these files (packaged registry content; the source links show where each ships from):

- [components/ui/tabs.tsx](https://r.assistant-ui.com/base/files/tabs/components/ui/tabs.tsx) ([source](https://github.com/assistant-ui/assistant-ui/blob/main/packages/ui/src/components/react/ui/base/tabs.tsx))

```bash
curl -fsSL --create-dirs \
  -o 'components/ui/tabs.tsx' https://r.assistant-ui.com/base/files/tabs/components/ui/tabs.tsx
```

## Usage

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

export function Example() {
  return (
    <Tabs defaultValue="account">
      <TabsList>
        <TabsTrigger value="account">Account</TabsTrigger>
        <TabsTrigger value="password">Password</TabsTrigger>
      </TabsList>
      <TabsContent value="account">Account settings here.</TabsContent>
      <TabsContent value="password">Password settings here.</TabsContent>
    </Tabs>
  );
}
```

## Examples

### Variants

Use `default` for a contained control or `line` for navigation-style tabs.

\[interactive preview omitted]

```
<TabsList variant="default" />
<TabsList variant="line" />
```

### With icons

Tabs automatically style SVG icons placed inside triggers.

\[interactive preview component TabsWithIconsSample omitted]

Code for TabsWithIconsSample preview:

```tsx
"use client";

import { Bell, FileText, Lock, Settings, User } from "lucide-react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";

function TabsWithIconsSample() {
  return (
    <Tabs defaultValue="profile" className="w-[400px]">
      <TabsList>
        <TabsTrigger value="profile">
          <User />
          Profile
        </TabsTrigger>
        <TabsTrigger value="notifications">
          <Bell />
          Notifications
        </TabsTrigger>
        <TabsTrigger value="security">
          <Lock />
          Security
        </TabsTrigger>
      </TabsList>
      <TabsContent value="profile" className="p-4">
        <p className="text-muted-foreground text-sm">
          Edit your profile information.
        </p>
      </TabsContent>
      <TabsContent value="notifications" className="p-4">
        <p className="text-muted-foreground text-sm">
          Manage your notification preferences.
        </p>
      </TabsContent>
      <TabsContent value="security" className="p-4">
        <p className="text-muted-foreground text-sm">
          Configure security and privacy settings.
        </p>
      </TabsContent>
    </Tabs>
  );
}
```

### Controlled

Use `value` and `onValueChange` for controlled tab state.

\[interactive preview component TabsControlledSample omitted]

Code for TabsControlledSample preview:

```tsx
"use client";

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

function TabsControlledSample() {
  const [activeTab, setActiveTab] = useState("overview");

  return (
    <Tabs
      value={activeTab}
      onValueChange={setActiveTab}
      className="w-[400px]"
    >
      <TabsList variant="line">
        <TabsTrigger value="overview">Overview</TabsTrigger>
        <TabsTrigger value="analytics">Analytics</TabsTrigger>
        <TabsTrigger value="reports">Reports</TabsTrigger>
      </TabsList>
      <TabsContent value="overview" className="p-4">
        <p className="text-muted-foreground text-sm">Overview content</p>
      </TabsContent>
      <TabsContent value="analytics" className="p-4">
        <p className="text-muted-foreground text-sm">Analytics content</p>
      </TabsContent>
      <TabsContent value="reports" className="p-4">
        <p className="text-muted-foreground text-sm">Reports content</p>
      </TabsContent>
    </Tabs>
    <p className="text-muted-foreground text-sm">
      Current tab: <code className="font-mono">{activeTab}</code>
    </p>
  );
}
```

### As link

Compose with `render` in Base UI or `asChild` in Radix to render a trigger as a link.

\[interactive preview component TabsAsLinkSample omitted]

Code for TabsAsLinkSample preview:

```tsx
"use client";

import { Bell, FileText, Lock, Settings, User } from "lucide-react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";

function TabsAsLinkSample() {
  return (
    <Tabs defaultValue="docs">
      <TabsList variant="line">
        <TabsTrigger value="docs" render={<a href="#installation" />}>
          <FileText />
          Docs
        </TabsTrigger>
        <TabsTrigger value="api" render={<a href="#api-reference" />}>
          <Settings />
          API
        </TabsTrigger>
      </TabsList>
    </Tabs>
  );
}
```

## API Reference

### Composable API

| Component     | Description                                                |
| ------------- | ---------------------------------------------------------- |
| `Tabs`        | The root component that manages tab state and orientation. |
| `TabsList`    | The container for tab triggers.                            |
| `TabsTrigger` | An individual tab control.                                 |
| `TabsContent` | The content panel for a tab.                               |

### Tabs

- `defaultValue?`: `string` — The initial active tab for uncontrolled state.
- `value?`: `string` — The controlled active tab.
- `onValueChange?`: `(value: string) => void` — Called when the active tab changes.
- `orientation`: `"horizontal" | "vertical"` (default `"horizontal"`) — The direction of the tab list and keyboard navigation.

### TabsList

- `variant`: `"default" | "line"` (default `"default"`) — The visual style of the tab list.
- `className?`: `string` — Additional CSS classes.

### TabsTrigger

- `value`: `string` — The unique value for the tab.
- `disabled?`: `boolean` — Whether the tab is disabled.
- `render?`: `ReactElement | function` — Base UI: compose as a different element.
- `asChild`: `boolean` (default `false`) — Radix: merge props with a child element.

### TabsContent

- `value`: `string` — The value matching the corresponding trigger.
- `className?`: `string` — Additional CSS classes.

### Style variants

| Export             | Description                        |
| ------------------ | ---------------------------------- |
| `tabsListVariants` | Styles for the tab list container. |

```
import { tabsListVariants } from "@/components/ui/tabs";

<div className={tabsListVariants({ variant: "line" })}>
  Custom tab list
</div>
```