# Tabs

Tabs is a neobrutalist React component from Cruise UI. Three styles: Underline for page sections, Boxed for settings, Pill for filters.

Install (with the @cruiseui registry in components.json, see Installation):

```bash
npx shadcn@latest add @cruiseui/tabs
```

Import: `import { CruiseTabs } from "@/components/cruise/tabs";`

## When to use

Switching between views of the same thing without leaving the page.

## When not to

Tabs that are really pages (use links). More than ~6 tabs.

## Example (React)

```tsx
import { CruiseTabs } from "@/components/cruise/tabs";

export default function TabsExample() {
  return (
    <div className="flex flex-col gap-10">
      <CruiseTabs
        label="Product details"
        items={[
          { value: "details", label: "Details", content: <p>Three layers of vanilla sponge. Serves 12.</p> },
          { value: "reviews", label: "Reviews", content: <p>4.8 out of 5 from 126 reviews.</p> },
          { value: "delivery", label: "Delivery", content: <p>Same-day delivery in Lagos.</p> },
        ]}
      />
      <CruiseTabs
        variant="boxed"
        label="Settings"
        items={[
          { value: "profile", label: "Profile", content: <p>Your name, photo and phone number.</p> },
          { value: "security", label: "Security", content: <p>Password and two-step sign-in.</p> },
        ]}
      />
      <CruiseTabs
        variant="pill"
        label="Filter products"
        items={[
          { value: "all", label: "All", content: <p>Showing all 48 products.</p> },
          { value: "cakes", label: "Cakes", content: <p>Showing 18 cakes.</p> },
          { value: "drinks", label: "Drinks", content: <p>Showing 8 drinks.</p> },
        ]}
      />
    </div>
  );
}
```

## HTML

Needs theme.css (https://cruiseui.dev/theme.css).

```html
<div class="tabs-underline"> <!-- or tabs-boxed / tabs-pill -->
  <div class="tab-list" role="tablist" aria-label="Product details">
    <button type="button" class="tab" role="tab" id="tab-details" aria-selected="true" aria-controls="panel-details">Details</button>
    <button type="button" class="tab" role="tab" id="tab-reviews" aria-selected="false" aria-controls="panel-reviews" tabindex="-1">Reviews</button>
    <button type="button" class="tab" role="tab" id="tab-delivery" aria-selected="false" aria-controls="panel-delivery" tabindex="-1">Delivery</button>
  </div>
  <div class="tab-panel" role="tabpanel" id="panel-details" aria-labelledby="tab-details" tabindex="0">…</div>
  <div class="tab-panel" role="tabpanel" id="panel-reviews" aria-labelledby="tab-reviews" tabindex="0" hidden>…</div>
  <div class="tab-panel" role="tabpanel" id="panel-delivery" aria-labelledby="tab-delivery" tabindex="0" hidden>…</div>
</div>
```

## Props: CruiseTabs

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | — | Accessible name for the tab row, e.g. "Order details". |
| `items` | `CruiseTabItem<V>[]` | — | — |
| `variant?` | `CruiseTabsVariant` | `"underline"` | — |
| `value?` | `V` | — | — |
| `defaultValue?` | `V` | `items[0]?.value` | — |
| `onValueChange?` | `((value: V) => void)` | — | — |
| `keepMounted?` | `boolean` | `false` | Render every panel's content in the HTML (hidden until chosen), so it can be found without JavaScript and by search engines. |
| `className?` | `string` | — | — |

## Accessibility

- tablist / tab / tabpanel roles with aria-selected and aria-controls.
- Left / Right, Home / End move between tabs; the row scrolls sideways on phones.
