# Toast

Presentational toast — an inline-layout Notice dressed for the toast stack
(shadow, enter animation, icon | text | actions | × in one row).

The toast root is also a nested `.tui-interface` with `data-theme="dark"`:
a dark surface by default (following Tooltip's inverted treatment), done as
a theme SCOPE rather than a token remap — the toast accepts arbitrary
children, and everything inside (action Buttons, the dismiss IconButton,
icons, consumer content) resolves dark tokens for free. Pass
`data-theme="light"` (or "auto") through rest to opt out.

The DOM carries both `tui-toast` and `tui-notice` classes, so Notice's
component API tokens (`--tui-notice-bg`, `--tui-notice-padding`, …) can be
re-pointed per toast context: `.tui-toast { --tui-notice-bg: …; }`.

```tsx
import { Toast, ToastProvider, useToast } from '@tangible/ui';
```

Interactive docs and examples: [Toast in Storybook](https://storybook-tangible-ui.pages.dev/?path=/docs/overlays-toast--docs).

## Toast props

| Prop | Type | Default | Description |
| - | - | - | - |
| `actions?` | `React.ReactNode` | | Action content (e.g. a Button), rendered in the foot. |
| `announce?` | `"assertive" \| "polite"` | | Screen-reader announcement politeness. Defaults to 'assertive' (role="alert") for danger, 'polite' (role="status") otherwise. |
| `children?` | `React.ReactNode` | | Body/description content. |
| `className?` | `string` | | |
| `dismissible?` | `boolean` | `true` | Renders a dismiss (×) button. Default true. |
| `dismissLabel?` | `string` | | Accessible label for the dismiss button. Default 'Dismiss'. |
| `focusable?` | `boolean` | | Makes the toast root programmatically focusable (tabIndex -1, with a focus ring) — Notice's `focusable`, forwarded. ToastProvider sets it on every queued toast: the root is the focus target when a same-id replacement unmounts an instance that held focus. |
| `icon?` | `React.ReactNode` | | Icon content, rendered leading the text. Colored by theme via Notice. |
| `onDismiss?` | `() => void` | | Called after the exit animation completes (× button path). |
| `size?` | `"lg" \| "md" \| "sm"` | `'sm'` | Density preset (Notice's size scale). Default 'sm' — toasts are dense; 'md'/'lg' restore Notice's roomier panel spacing. |
| `style?` | `React.CSSProperties` | | |
| `theme?` | `"danger" \| "info" \| "neutral" \| "success" \| "warning"` | `'neutral'` | Visual intent. Default 'neutral' — the plain dark surface. |
| `title?` | `React.ReactNode` | | Title text — a styled `<div>`, never a heading: a toast lives in a portal outside the document outline, so a heading would be an orphan for screen-reader heading navigation. |

Also accepts the standard attributes of `HTMLAttributes` (`data-*`, `aria-*`, event handlers), passed to the element it renders.

## ToastProvider props

| Prop | Type | Default | Description |
| - | - | - | - |
| `children?` | `React.ReactNode` | | |
| `container?` | `Element \| null` | | Optional portal target (mirrors Modal). Defaults to the portal root of the nearest `.tui-interface`. |
| `duration?` | `number` | `5000` | Default auto-dismiss delay in ms. Default 5000. |
| `max?` | `number` | `5` | Most toasts the stack shows at once — older ones are dismissed to make room. Default 5; pass Infinity to disable. |
| `placement?` | `"bottom" \| "bottom-end" \| "bottom-start" \| "top" \| "top-end" \| "top-start"` | `'bottom-end'` | Where the toast stack anchors. Default 'bottom-end'. |
| `regionLabel?` | `string` | `'Notifications'` | Accessible name for the toast region landmark. Default 'Notifications'. If a page hosts multiple providers (e.g. several independent `.tui-interface` widgets), give each a unique label — duplicate region landmark names are ambiguous for AT users. |

## Hooks

### useToast

```ts
useToast(): ToastContextValue
```

Returns:

| Member | Type | Description |
| - | - | - |
| `toast` | `(options?: ToastOptions) => string` | Show a toast. Returns its id. |
| `dismiss` | `(id: string) => void` | Dismiss one toast by id (plays its exit animation). |
| `dismissAll` | `() => void` | Dismiss all toasts. |

`ToastOptions` (the `options` of `toast`):

| Member | Type | Description |
| - | - | - |
| `size?` | `"lg" \| "md" \| "sm"` | Density preset (Notice's size scale). Default 'sm' — toasts are dense; 'md'/'lg' restore Notice's roomier panel spacing. |
| `className?` | `string` | |
| `style?` | `React.CSSProperties` | |
| `title?` | `React.ReactNode` | Title text — a styled `<div>`, never a heading: a toast lives in a portal outside the document outline, so a heading would be an orphan for screen-reader heading navigation. |
| `theme?` | `"danger" \| "info" \| "neutral" \| "success" \| "warning"` | Visual intent. Default 'neutral' — the plain dark surface. |
| `icon?` | `React.ReactNode` | Icon content, rendered leading the text. Colored by theme via Notice. |
| `announce?` | `"assertive" \| "polite"` | Screen-reader announcement politeness. Defaults to 'assertive' (role="alert") for danger, 'polite' (role="status") otherwise. |
| `dismissible?` | `boolean` | Renders a dismiss (×) button. Default true. |
| `onDismiss?` | `() => void` | Called after the exit animation completes (× button path). |
| `dismissLabel?` | `string` | Accessible label for the dismiss button. Default 'Dismiss'. |
| `actions?` | `React.ReactNode` | Action content (e.g. a Button), rendered in the foot. |
| `id?` | `string` | Stable id. Calling toast() again with the same id updates that toast in place (remounting it, so it re-animates and re-announces) and restarts its timer. Omit for a generated id. |
| `description?` | `React.ReactNode` | Body content — maps to the presentational `<Toast>`'s children. |
| `duration?` | `number \| null` | Auto-dismiss delay in ms. `null` persists until dismissed. Defaults to the provider's `duration` — unless the toast has `actions`, in which case it persists (the user needs time to act; WCAG 2.2.1). |
| `data-testid?` | `string` | Playwright hook — lands on the toast root, per house testid policy. |

## Examples

- [Placements](https://storybook-tangible-ui.pages.dev/?path=/story/overlays-toast--placements): One provider per placement for demo purposes — a real app renders a single provider (and if it genuinely needs several, each must get a unique `regionLabel`). Default is `bottom-end`.

- [Update By Id](https://storybook-tangible-ui.pages.dev/?path=/story/overlays-toast--update-by-id): Calling `toast()` again with the same `id` replaces that toast (it remounts, so it re-animates and re-announces) and restarts its timer — safe even if the first toast is already animating out.

Other stories: Static, Static Themes, Static With Actions, Basic, One-Liner (Self-Dismissing), Themes, With Actions, Persistent And Dismiss All ([interactive page](https://storybook-tangible-ui.pages.dev/?path=/docs/overlays-toast--docs)).

## Component API tokens

Read via fallback, never declared. Set one on an ancestor to restyle every instance under it.

- `--tui-toast-width`
- `--tui-toast-fg`
- `--tui-toast-gap`
- `--tui-toast-inset`
- `--tui-toast-shadow`
- `--tui-toast-z`

---

Interactive version: https://storybook-tangible-ui.pages.dev/?path=/docs/overlays-toast--docs
