# Tabs

> A tab bar that switches views.

Component · Navigation · Halo kit · [Live page](https://ui.twentyfirst.media/halo/components/Tabs/)

A tab bar that switches views. With `panels` it renders the panels too, wired with the tab,
tablist and tabpanel roles; without, it is a bar you connect to your own content.

- Keyboard: ←/→ move between tabs and select them, Home/End jump; only the selected tab is in the
  tab order.
- `block` stretches the tabs to the full width.

## Example

```tsx
import { KeyValue, Panel, Tabs } from "@twentyfirstmedia/halo";

export default function Preview() {
  return (
    <Panel title="Northwind">
      <Tabs
        label="Customer"
        items={["Overview", "Invoices", "Notes"]}
        panels={{
          Overview: (
            <KeyValue
              items={[
                { k: "Plan", v: "Team · 24 seats" },
                { k: "MRR", v: "€1,240" },
                { k: "Renews", v: "May 1, 2026" },
              ]}
            />
          ),
          Invoices: <p className="tf-card-desc">Three invoices this year, all paid.</p>,
          Notes: <p className="tf-card-desc">Wants 40 more seats before the renewal.</p>,
        }}
      />
    </Panel>
  );
}
```

## Props

### Tabs

| Prop | Type | Notes |
| --- | --- | --- |
| `items` | `string[]` | Required |
| `value?` | `string` |  |
| `defaultValue?` | `string` |  |
| `onChange?` | `(v: string) => void` |  |
| `block?` | `boolean` |  |
| `panels?` | `Record<string, ReactNode>` | Content per tab; renders the tab panels under the bar, wired with tab/tabpanel roles. |
| `label?` | `string` | Accessible name of the tab list. |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Panel

| Prop | Type | Notes |
| --- | --- | --- |
| `side?` | `boolean` |  |
| `title?` | `string` |  |
| `subtitle?` | `string` |  |
| `action?` | `ReactNode` |  |
| `children?` | `ReactNode` |  |
| `surface?` | `Surface` | `"glass"`: translucent glass over what is behind (maps, 3D, video, photos); `"solid"` opts out inside a glass `UIProvider`. |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### KeyValue

| Prop | Type | Notes |
| --- | --- | --- |
| `items` | `KeyValueItem[]` | Required |
| `dense?` | `boolean` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |
