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

Owns the toast queue, its auto-dismiss timers, and the single ToastRegion (D65). This is the library's one stateful container, and the exception is deliberately narrow. D50 and D53 rejected internal state for Dialog and Menu because the consumer already owned the state that decided visibility — a menu is open because a user clicked a trigger the consumer rendered. A toast has no such owner: it is created by an outcome, not by a UI state, and it disappears on a timer nobody is watching. The rule that survives is the useful half — presentational components stay controlled (`Toast` still holds nothing), a stateful container may exist when the state has no natural owner, and it must be opt-in. Timers pause while the pointer or focus is inside the region (WCAG 2.2.1), and resume with the time *remaining* rather than a fresh full duration — restarting would let a user hold a toast open indefinitely by jiggling the mouse.

## Props

| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
| `limit` | `number` | 3 | no | Max simultaneous toasts; the oldest is evicted first. |
| `duration` | `number` | 5000 | no | Auto-dismiss for toasts with no action, in ms. |
| `actionDuration` | `number` | 10000 | no | Auto-dismiss for toasts carrying an action, in ms. An affordance that vanishes before it can be reached is not an affordance. |
| `placement` | `"top-start" \| "top-end" \| "bottom-start" \| "bottom-end"` | bottom-end | no | Corner the stack occupies. |
| `children` | `ReactNode` | — | yes | The subtree that may call `useToast()`. The region is rendered alongside it. |

## Keyboard & assistive tech

| Keys | Behavior |
|---|---|
| Tab | Focus entering the region pauses every auto-dismiss timer; leaving resumes them. |

Owns the queue, the auto-dismiss timers and the single ToastRegion (D65). Timers pause while the pointer or focus is inside the region and resume with the time remaining, satisfying WCAG 2.2.1 for content that disappears on a timer. Toasts carrying an action get a longer default lifetime, so the affordance cannot vanish before it is reached. useToast() throws outside a provider rather than silently no-opping.

## Theming

This component has no `--psi-toast-provider-*` 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.
