# Tabs

> Compound tab interface with roving tabindex, automatic activation, and vertical/horizontal orientation.

- Available in: `@sisyphos-ui/react`, `@sisyphos-ui/vue`, `@sisyphos-ui/angular`
- Docs: https://sisyphosui.com/docs/components/tabs

## Installation

Pick the framework binding that matches your stack:

```bash
pnpm add @sisyphos-ui/react   # React 18+
pnpm add @sisyphos-ui/vue     # Vue 3+
pnpm add @sisyphos-ui/angular # Angular 17+
```

## Import

```tsx
import "@sisyphos-ui/react/styles.css";
import { Tabs } from "@sisyphos-ui/react";
```

## Framework usage

### React 18+

```tsx
import { useState } from "react";
import { Tabs } from "@sisyphos-ui/react";

export const Settings = () => {
  const [tab, setTab] = useState("profile");
  return (
    <Tabs value={tab} onValueChange={setTab}>
      <Tabs.List>
        <Tabs.Trigger value="profile">Profile</Tabs.Trigger>
        <Tabs.Trigger value="billing">Billing</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Panel value="profile">Profile content.</Tabs.Panel>
      <Tabs.Panel value="billing">Billing content.</Tabs.Panel>
    </Tabs>
  );
};
```

### Vue 3+

```vue
<script setup lang="ts">
import { ref } from "vue";
import { Tabs, TabsList, TabsTrigger, TabsPanel } from "@sisyphos-ui/vue";
const tab = ref("profile");
</script>

<template>
  <Tabs v-model:value="tab">
    <TabsList>
      <TabsTrigger value="profile">Profile</TabsTrigger>
      <TabsTrigger value="billing">Billing</TabsTrigger>
    </TabsList>
    <TabsPanel value="profile">Profile content.</TabsPanel>
    <TabsPanel value="billing">Billing content.</TabsPanel>
  </Tabs>
</template>
```

### Angular 17+

```ts
import { Component, signal } from "@angular/core";
import { Tabs, TabsList, TabsTrigger, TabsPanel } from "@sisyphos-ui/angular";

@Component({
  selector: "app-settings",
  standalone: true,
  imports: [Tabs, TabsList, TabsTrigger, TabsPanel],
  template: `
    <sui-tabs [(value)]="tab">
      <sui-tabs-list>
        <sui-tabs-trigger value="profile">Profile</sui-tabs-trigger>
        <sui-tabs-trigger value="billing">Billing</sui-tabs-trigger>
      </sui-tabs-list>
      <sui-tabs-panel value="profile">Profile content.</sui-tabs-panel>
      <sui-tabs-panel value="billing">Billing content.</sui-tabs-panel>
    </sui-tabs>
  `,
})
export class SettingsComponent {
  tab = signal("profile");
}
```

## Examples

### Default

`Tabs.List`, `Trigger`, `Panel` compose a tab interface with roving tabindex.

```tsx
import { Tabs } from "@sisyphos-ui/react";

export function Example() {
  return (
    <Tabs defaultValue="preview" className="w-full max-w-lg">
      <Tabs.List>
        <Tabs.Trigger value="preview">Preview</Tabs.Trigger>
        <Tabs.Trigger value="code">Code</Tabs.Trigger>
        <Tabs.Trigger value="spec">Spec</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Panel value="preview" className="pt-4">Render a visual preview of the component here.</Tabs.Panel>
      <Tabs.Panel value="code"    className="pt-4">Show the source code for the example.</Tabs.Panel>
      <Tabs.Panel value="spec"    className="pt-4">Describe the design spec and motion details.</Tabs.Panel>
    </Tabs>
  );
}
```

### Pill variant

```tsx
import { Tabs } from "@sisyphos-ui/react";

export function Example() {
  return (
    <Tabs defaultValue="overview" variant="pill" className="w-full max-w-md">
      <Tabs.List>
        <Tabs.Trigger value="overview">Overview</Tabs.Trigger>
        <Tabs.Trigger value="billing">Billing</Tabs.Trigger>
        <Tabs.Trigger value="team">Team</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Panel value="overview" className="pt-4">Dashboard overview…</Tabs.Panel>
      <Tabs.Panel value="billing"  className="pt-4">Billing details…</Tabs.Panel>
      <Tabs.Panel value="team"     className="pt-4">Team members…</Tabs.Panel>
    </Tabs>
  );
}
```

### Vertical orientation

Arrow keys walk Up/Down; Home/End jump to first/last.

```tsx
import { Tabs } from "@sisyphos-ui/react";

export function Example() {
  return (
    <Tabs orientation="vertical" defaultValue="profile">
      <Tabs.List>
        <Tabs.Trigger value="profile">Profile</Tabs.Trigger>
        <Tabs.Trigger value="security">Security</Tabs.Trigger>
        <Tabs.Trigger value="notifications">Notifications</Tabs.Trigger>
        <Tabs.Trigger value="billing">Billing</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Panel value="profile">Manage display name, avatar, handle.</Tabs.Panel>
      <Tabs.Panel value="security">Change password, 2FA, login history.</Tabs.Panel>
      <Tabs.Panel value="notifications">Channels per event type.</Tabs.Panel>
      <Tabs.Panel value="billing">Payment method and invoices.</Tabs.Panel>
    </Tabs>
  );
}
```

### Full width

`fullWidth` stretches triggers evenly — pairs well with the `soft` variant.

```tsx
import { Tabs } from "@sisyphos-ui/react";

export function Example() {
  return (
    <Tabs defaultValue="day" fullWidth variant="soft">
      <Tabs.List>
        <Tabs.Trigger value="day">Day</Tabs.Trigger>
        <Tabs.Trigger value="week">Week</Tabs.Trigger>
        <Tabs.Trigger value="month">Month</Tabs.Trigger>
        <Tabs.Trigger value="year">Year</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Panel value="day">Today's metrics.</Tabs.Panel>
      <Tabs.Panel value="week">Week-over-week trends.</Tabs.Panel>
      <Tabs.Panel value="month">Monthly cohort analysis.</Tabs.Panel>
      <Tabs.Panel value="year">Annual review.</Tabs.Panel>
    </Tabs>
  );
}
```

### With icons

Each `Tabs.Trigger` accepts an `icon` prop rendered before the label.

```tsx
import { Tabs } from "@sisyphos-ui/react";

const TeamIcon = () => (
  <svg viewBox="0 0 24 24" width={16} height={16} aria-hidden="true">
    <path fill="currentColor" d="M8 11a3 3 0 100-6 3 3 0 000 6zm8 0a3 3 0 100-6 3 3 0 000 6zm-8 2c-2.67 0-8 1.34-8 4v2h10v-2c0-.97.49-1.8 1.23-2.42C10.48 13.22 9.27 13 8 13zm8 0c-.29 0-.62.02-.97.06 1.14.83 1.92 1.94 1.92 3.4V18h7v-2c0-2.66-5.33-4-8-4z" />
  </svg>
);
const BellIcon = () => (
  <svg viewBox="0 0 24 24" width={16} height={16} aria-hidden="true">
    <path fill="currentColor" d="M12 2a6 6 0 00-6 6v3.586L4.293 13.293A1 1 0 005 15h14a1 1 0 00.707-1.707L18 11.586V8a6 6 0 00-6-6zm0 20a3 3 0 003-3H9a3 3 0 003 3z" />
  </svg>
);
const BillingIcon = () => (
  <svg viewBox="0 0 24 24" width={16} height={16} aria-hidden="true">
    <path fill="currentColor" d="M20 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V6a2 2 0 00-2-2zm0 4H4V6h16v2zm0 10H4v-6h16v6z" />
  </svg>
);

export function Example() {
  return (
    <Tabs defaultValue="team">
      <Tabs.List>
        <Tabs.Trigger value="team" icon={<TeamIcon />}>Team</Tabs.Trigger>
        <Tabs.Trigger value="notifications" icon={<BellIcon />}>Notifications</Tabs.Trigger>
        <Tabs.Trigger value="billing" icon={<BillingIcon />}>Billing</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Panel value="team">Invite, remove, and manage roles.</Tabs.Panel>
      <Tabs.Panel value="notifications">Configure email and push.</Tabs.Panel>
      <Tabs.Panel value="billing">Plan and payment history.</Tabs.Panel>
    </Tabs>
  );
}
```

<!-- exports: { "Tabs": "@sisyphos-ui/react" } -->