# Toast

Toasts show short-lived feedback in a fixed stack at the bottom right of the page. Call **`SonicToast.add()`** (also `window.SonicToast`); the **`sonic-toast`** host is created on first use. Use **`label`** for a heading and **`preserve`** when the user must read or act before the toast goes away.

## Basic example

<sonic-code>
  <template>
    <sonic-button onclick="SonicToast.add({ text: 'Flight CN 001 is now boarding' })">
      Show toast
    </sonic-button>
  </template>
</sonic-code>

## Status

**`status`** sets the color, the icon and the live-region role. With no `status`, the toast is neutral.

<sonic-code>
  <template>
    <div class="flex flex-wrap gap-2">
      <sonic-button onclick="SonicToast.add({ text: 'Default message' })">Default</sonic-button>
      <sonic-button onclick="SonicToast.add({ text: 'Operation succeeded', status: 'success' })">Success</sonic-button>
      <sonic-button onclick="SonicToast.add({ text: 'Something went wrong', status: 'error' })">Error</sonic-button>
      <sonic-button onclick="SonicToast.add({ text: 'Check this detail', status: 'warning' })">Warning</sonic-button>
      <sonic-button onclick="SonicToast.add({ text: 'Helpful context', status: 'info' })">Info</sonic-button>
    </div>
  </template>
</sonic-code>

## Label

**`label`** adds a bold heading above **`text`**. `title` is a deprecated alias.

<sonic-code>
  <template>
    <sonic-button
      onclick="SonicToast.add({ label: 'Gate change', text: 'Flight CN 001 now departs from gate B12.', status: 'warning' })"
    >
      Toast with label
    </sonic-button>
  </template>
</sonic-code>

## HTML in text

**`text`** and **`label`** accept HTML strings. A link or form control in **`text`** turns on **`preserve`** automatically.

<sonic-code>
  <template>
    <sonic-button
      onclick="SonicToast.add({ text: 'Message with <strong>HTML</strong> and an <a href=&quot;#&quot;>action link</a>', status: 'info' })"
    >
      Toast with HTML
    </sonic-button>
  </template>
</sonic-code>

## Preserve

Toasts hide after 6 seconds; the timer pauses on hover and focus. **`preserve`** keeps the toast until the user closes it.

<sonic-code>
  <template>
    <sonic-button
      onclick="SonicToast.add({ text: 'Turbulence ahead: please fasten your seat belt', status: 'info', preserve: true })"
    >
      Persistent toast
    </sonic-button>
  </template>
</sonic-code>

## Dismiss forever

With **`dismissForever`** and a stable **`id`**, closing the toast is stored in `localStorage` and later `add()` calls with that `id` are ignored. A toast identical to one already shown (ignoring `id`) is never added twice.

<sonic-code>
  <template>
    <sonic-button
      onclick="SonicToast.add({ id: 'welcome-toast', label: 'Welcome', text: 'Close me and I will not come back after a reload.', status: 'info', dismissForever: true })"
    >
      Dismiss forever
    </sonic-button>
  </template>
</sonic-code>

## Ghost

**`ghost`** renders a semi-transparent, non-interactive toast, for example for a background task.

<sonic-code>
  <template>
    <sonic-button
      onclick="SonicToast.add({ text: 'Syncing in the background', status: 'info', ghost: true })"
    >
      Ghost toast
    </sonic-button>
  </template>
</sonic-code>

## Removing toasts

Static helpers clear the stack from script, for example after navigation. **`removeAll()`** keeps ghost toasts; **`removeTemporaryItems()`** keeps preserved ones.

<sonic-code>
  <template>
    <div class="flex flex-wrap gap-2">
      <sonic-button onclick="SonicToast.add({ text: 'Temporary success', status: 'success' })">Add success</sonic-button>
      <sonic-button onclick="SonicToast.add({ text: 'Temporary error', status: 'error' })">Add error</sonic-button>
      <sonic-button onclick="SonicToast.add({ text: 'Persistent info', status: 'info', preserve: true })">Add persistent</sonic-button>
    </div>
    <div class="flex flex-wrap gap-2 mt-3">
      <sonic-button variant="outline" onclick="SonicToast.removeItemsByStatus('success')">Remove success</sonic-button>
      <sonic-button variant="outline" onclick="SonicToast.removeTemporaryItems()">Remove temporary</sonic-button>
      <sonic-button variant="outline" onclick="SonicToast.removeAll()">Remove all</sonic-button>
    </div>
  </template>
</sonic-code>

Inside an iframe, toasts are forwarded to the parent window's stack when the parent also loads Concorde.

## API reference

Options of **`SonicToast.add(options)`**:

| Option | Values | Description |
|----------|---------|-------------|
| `text` | string · Lit template | Body, required; HTML strings allowed |
| `label` | string · Lit template | Heading above `text` |
| `title` | string · Lit template | Deprecated alias of `label` |
| `status` | `success` · `error` · `warning` · `info` (default neutral) | Color and icon; `error` gets `role="alert"`, others `role="status"` |
| `id` | string · number (default timestamp) | Identifier for `removeItemById` and `dismissForever` |
| `preserve` | boolean | No auto-hide; forced when `text` contains a link or control |
| `ghost` | boolean | Semi-transparent and non-interactive; kept by `removeAll` |
| `dismissForever` | boolean | Remember the dismissal in `localStorage`; needs a stable `id` |
| `styleSheet` | `CSSResult` · `CSSStyleSheet` · array | Extra styles adopted by the toast |
| `useSlot` | boolean | Legacy: render `text` in the light DOM |

| Method | Description |
|--------|-------------|
| `SonicToast.add(options)` | Show a toast; returns the stored config, or `null` when skipped |
| `SonicToast.removeAll()` | Remove every toast except ghosts |
| `SonicToast.removeItemsByStatus(status)` | Remove toasts with this `status` |
| `SonicToast.removeItemById(id)` | Remove one toast |
| `SonicToast.removeTemporaryItems()` | Remove toasts without `preserve` |

`sonic-toast` and `sonic-toast-item` are created by `add()`; do not write them in markup. `sonic-toast-message-subscriber` shows a toast for each `{ type: "public", content, status }` entry of its `messages` property.
