# Toast

> A transient message in the corner, added from script into a region the page rendered.

A toast is the one component here that cannot be static: it appears in response to something happening. The page renders an empty region with `toasts()`, and `toast()` from `sitelo/ui/client` appends to it.

The region is a polite live region, so anything appended is announced without stealing focus.

## Setting it up

Put the region anywhere in the body — it is fixed-position, so where does not matter:

`src/index.ht.js`

```javascript
import { toasts } from 'sitelo/ui'

body(
  // …the page…
  toasts(),
)
```

This is the one part of the runtime nothing on the page triggers for you, so it is the one part you reach yourself — from an event attribute, with nothing bundled:

`Anywhere`

```javascript
button({ onclick: "import('/su/toast.js').then(m=>m.toast('Saved.',{color:'success'}))" }, 'Save')
```

Or from your own module, when there is already one running:

`src/main.js`

```javascript
import { toast } from 'sitelo/ui/client'

toast('Saved.', { color: 'success' })
```

## Try it

This page renders a `toasts()` region and the buttons below fetch the runtime themselves, so they really do produce toasts — bottom right. Nothing is loaded until you press one.

```javascript
stack({ direction: 'row', gap: 'sm', wrap: true },
  button({
    variant: 'soft',
    color: 'success',
    onclick: "import('/su/toast.js').then(m=>m.toast('Saved.',{color:'success'}))",
  }, 'Success'),
  button({
    variant: 'soft',
    color: 'warning',
    onclick: "import('/su/toast.js').then(m=>m.toast('Two pages have no meta description.',{color:'warning'}))",
  }, 'Warning'),
  button({
    variant: 'soft',
    color: 'danger',
    onclick: "import('/su/toast.js').then(m=>m.toast('The build failed. Check the link report.',{color:'danger'}))",
  }, 'Danger'),
  button({
    variant: 'soft',
    color: 'neutral',
    onclick: "import('/su/toast.js').then(m=>m.toast('This one stays until you close it.',{color:'neutral',duration:0}))",
  }, 'Until dismissed'),
)
```

## Options

`duration` is how long the toast stays, in milliseconds; `0` keeps it up until someone closes it. Every toast gets a close button, wired to the same dismiss handler an alert uses.

`Options`

```javascript
toast('Saved.', { color: 'success' })
toast('Still working…', { color: 'neutral', duration: 0 })
toast('Deployed in 1.7s', { color: 'success', duration: 8000 })
```

## What it renders

A toast is an `alert()` in the toasts region — same markup, same colours, same dismiss button. Nothing new to learn, and nothing extra to style.

```javascript
stack({ gap: 'sm', style: 'width: 100%; max-width: 24rem' },
  alert({ color: 'success', dismissible: true }, 'Saved.'),
  alert({ color: 'danger', dismissible: true }, 'The build failed. Check the link report.'),
)
```

## When to use one

A toast is for confirming something the reader just did. It is the wrong place for anything they need to act on or read carefully — it disappears, it is easy to miss, and on a static site most messages belong in the page itself as an `alert()`.

## Props

`toasts()` takes no props of its own. `toast()` from `sitelo/ui/client`:

| Argument | Type | Default | Description |
| --- | --- | --- | --- |
| `message` | `string` | — | The text. Set as textContent, so it is never parsed as markup. |
| `color` | `'primary' \| 'neutral' \| 'success' \| 'warning' \| 'danger'` | `'neutral'` | Which palette to use. |
| `duration` | `number` | `4000` | Milliseconds before it disappears. 0 keeps it up. |

It returns the element it added, or `null` when the page has no `toasts()` region.
