<!-- Generated by emit-docs.ts — do not edit. -->
# TabList

The `role="tablist"` container (D67). Owns the roving tabindex: the whole list is one Tab stop, and the arrow keys move between tabs inside it.

## Props

| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
| `aria-label` | `string` | — | no | Accessible name for the tab set. Declared here rather than inherited so docgen keeps it in the manifest (D60) — a tablist without a name is announced as an unlabelled group, and the prop would otherwise be invisible to an agent reading the manifest. |
| `children` | `ReactNode` | — | yes | One `Tab` per view. |
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
| `ref` | `Ref<HTMLDivElement>` | — | no | Forwarded ref to the tablist element. |

## Keyboard & assistive tech

| Keys | Behavior |
|---|---|
| Arrow Left / Arrow Right | Horizontal orientation: moves to the previous/next enabled tab, wrapping at both ends. Selection follows focus (automatic activation). |
| Arrow Up / Arrow Down | Vertical orientation: the same, on the block axis. The cross-axis arrows are ignored rather than swallowed. |
| Home / End | Jumps to the first or last enabled tab. |

Renders role="tablist" with aria-orientation. Requires an accessible name — pass aria-label, which is promoted onto its own props interface (D60) so the manifest shows it. Owns the roving tabindex: exactly one tab is in the page tab order at a time.

## Theming

This component has no `--psi-tab-list-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.



## Rules

- One accent per visual group; everything else neutral or ghost.
- danger only for actions with real consequences.
- Sizes are px numbers (24|32|40|48), never S/M/L.
- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
