# Toast
Short notices that stack at an edge of the screen, pause on hover and close on their own or with a swipe.
```ehtml Example
import { Toaster, Toast, toast } from "@elements/ui/toast";
import { Button } from "@elements/ui/button";
```
## Parts
| Part | What it is |
|---|---|
| `Toaster` | The region toasts render in: a top-layer `` with one stack per position. Mount it once, in the app shell. |
| `Toast` | A declarative toast: shown while open is true; writes open = false back when it closes itself (timer, swipe, close, Escape, action). A literal open is uncontrolled: it shows when it renders. |
| `toast()` | The imperative API, imported beside Toaster: toast(title, options), toast.success, info, warning, error, loading, message, promise, custom, update, dismiss, getToasts (getActiveToasts) and getHistory. Same id updates a toast in place. |
| `.toast` | One toast: .toast-close, .toast-icon (loader and icon in one cell), .toast-arrow (anchored, with positioner.arrow), .toast-content (.toast-title, .toast-description), .toast-cancel, .toast-action. A toast.custom() toast holds .toast-custom instead. |
## Attributes
### Toaster
| Attribute | Type | Default | Description |
|---|---|---|---|
| `position` | `"top-left" \| "top-center" \| "top-right" \| "bottom-left" \| "bottom-center" \| "bottom-right"` | `"bottom-right"` | Where the stack sits. A toast may name its own position; it then renders in a second stack. |
| `expand` | `boolean` | `false` | Keep the stack fanned out. Otherwise it fans out on hover, focus or the hotkey. |
| `visibleToasts` | `number` | `3` | Toasts past this many are hidden and inert until those in front close. |
| `duration` | `number` | `4000` | Default time on screen in ms. A toast's own duration wins; Infinity stays until dismissed. |
| `gap` | `number` | `-1` | px between fanned-out toasts. -1 reads the theme (--space-3-5). |
| `offset` | `string \| number \| { top, right, bottom, left }` | `""` | Distance from the viewport edges. "" reads the theme (--space-6). |
| `mobileOffset` | `string \| number \| { top, right, bottom, left }` | `""` | The same under 600px. "" reads the theme (--space-4). |
| `closeButton` | `boolean` | `false` | A close button on every toast. |
| `richColors` | `boolean` | `false` | Success, info, warning and error toasts take their status colors. |
| `invert` | `boolean` | `false` | Inverse colors: a dark toast on a light page. |
| `theme` | `"" \| "light" \| "dark" \| "system"` | `""` | Light or dark toasts whatever the page's mode; system follows the OS. "" follows the page. |
| `hotkey` | `string[]` | `["altKey", "KeyT"]` | Focuses the region and fans out the stack. Each entry is a modifier property or an event.code or key, such as ["F8"]. |
| `dir` | `"ltr" \| "rtl" \| "auto"` | `"auto"` | Text direction of the stacks; auto reads the document. |
| `swipeDirections` | `SwipeDirection[]` | `[]` | Directions a swipe may dismiss toward. [] derives them from the position (bottom-right: bottom and right). |
| `swipeThreshold` | `number` | `45` | px a swipe must travel to dismiss on release. A quick flick also dismisses. |
| `id` | `string` | `""` | Names this Toaster; only toasts with the same toasterId render in it. |
| `label` | `string` | `"Notifications"` | The region's name; the hotkey is appended. |
| `ariaLabel` | `string` | `""` | Replaces the whole region name. |
| `closeButtonLabel` | `string` | `"Close toast"` | The close button's accessible name. |
| `icons` | `{ success?, info?, warning?, error?, loading?, close?: IconName \| false }` | `{}` | Replace or hide the icon per type. |
| `toastOptions` | `{ class?, classes?, style?, duration?, closeButton?, unstyled?, closeButtonLabel? }` | `{}` | Defaults for every toast in this Toaster. |
| `class` | `string` | `""` | Extra classes on the region. |
| `style` | `string` | `""` | Inline style on the region. |
### Toast
| Attribute | Type | Default | Description |
|---|---|---|---|
| `open` | `boolean` (two-way) | `false` | Shows the toast while true. Bind it; the toast writes false back when it closes itself. |
| `title, description, type` | `string \| ((t: ToastItem) => string), string \| ((t: ToastItem) => string), ToastType` | `"", "", "default"` | Its content and kind. |
| `duration, dismissible, closeButton, richColors, invert, important, icon, action, cancel, position, toasterId, swipeDirections, testId, class` | `as the toast() options` | `as the toast() options` | The same options as toast(). |
| `onOpenChange` | `(open: boolean) => void` | `() => {}` | Called when the toast closes itself; not when the caller sets open. |
| `onEscapeKeyDown, onPause, onResume, onSwipeStart, onSwipeMove, onSwipeEnd, onSwipeCancel` | `functions` | `() => {}` | As the toast() options. |
### toast() options
| Attribute | Type | Default | Description |
|---|---|---|---|
| `description` | `string \| ((t: ToastItem) => string)` | `""` | Second line under the title. A function is given the toast and re-renders when what it reads changes. |
| `data` | `unknown` | `undefined` | Your own values, for a function title or description (t.data) and toast.custom(). |
| `anchor` | `Element \| null` | `null` | Shows the toast next to this element instead of in the stack. |
| `positioner` | `{ side?, align?, sideOffset?, alignOffset?, arrow?, arrowPadding?, collisionAvoidance?, collisionBoundary?, collisionPadding?, sticky?, positionMethod?, disableAnchorTracking?, class?, style? }` | `{}` | How an anchored toast sits against its anchor; side defaults to top. arrow draws one pointing at the anchor. |
| `swipeDirections` | `SwipeDirection[]` | `the Toaster's` | The directions that dismiss this toast, over the Toaster's. |
| `id` | `string \| number` | `generated` | Reuse an id to update a toast in place; its timer restarts. |
| `action` | `{ label, onClick?, altText?, class?, style? } \| Node` | `none` | A primary button. It closes the toast unless onClick calls e.preventDefault(). altText is read to screen readers. An element of your own renders in its place and keeps its own handlers. |
| `cancel` | `{ label, onClick?, class?, style? } \| Node` | `none` | A secondary button; runs onClick and closes. An element of your own renders in its place. |
| `duration` | `number` | `the Toaster's` | ms on screen; Infinity stays. |
| `dismissible` | `boolean` | `true` | false: no swipe, no close, no Escape. |
| `icon` | `IconName \| false` | `the type's` | Replace the type icon, or hide it. |
| `important` | `boolean` | `false` | Announced assertively, interrupting the screen reader. |
| `closeButton, richColors, invert, position, toasterId` | `as on Toaster` | `the Toaster's` | Override the Toaster's for this toast. |
| `testId, class, classes, style, unstyled` | `string, string, ToastClasses, string, boolean` | `"", "", {}, "", false` | data-testid, extra classes (per part with classes), inline style, and no chrome. |
| `onDismiss, onAutoClose, onPause, onResume, onEscapeKeyDown, onSwipeStart, onSwipeMove, onSwipeEnd, onSwipeCancel` | `functions` | `none` | Closed by the user or toast.dismiss; closed by its timer; timer paused and resumed; Escape (preventable); swipe phases. |
| `onClose, onRemove` | `(t: ToastItem) => void` | `none` | The toast starts to close, for any reason; its exit finished and it left the page. |
## Keyboard
| Keys | Action |
|---|---|
| `Alt + T` | The hotkey: focuses the region and fans out the stack, from anywhere on the page. Pressed again from inside, returns focus. |
| `Tab / Shift + Tab` | Moves through the toasts, newest first, and their buttons. Tab past the last returns focus to where the hotkey was pressed. |
| `Space / Enter` | On the action, cancel or close button: runs it and closes the toast. |
| `Escape` | On a toast: closes it and moves focus to the next. On the region: folds the stack and returns focus. |
## Data attributes
| Attribute | Values | On | Description |
|---|---|---|---|
| `data-y-position, data-x-position` | `"top" \| "bottom"; "left" \| "center" \| "right"` | .toaster-list, .toast | |
| `data-expanded` | `"true" \| "false"` | .toaster-list, .toast | Fanned out. |
| `data-type` | `"default" \| "success" \| "info" \| "warning" \| "error" \| "loading"` | .toast | |
| `data-mounted` | `"true" \| "false"` | .toast | false for the first frame; the enter transition runs off it. |
| `data-removed` | `"true" \| "false"` | .toast | true during the exit. |
| `data-state` | `"open" \| "closed"` | .toast | closed during the exit. |
| `data-front` | `"true" \| "false"` | .toast | The newest toast. |
| `data-visible` | `"true" \| "false"` | .toast | false past visibleToasts. |
| `data-index` | 0..n | .toast | |
| `data-swiping, data-swiped, data-swipe-out` | `"true" \| "false"` | .toast | |
| `data-swipe` | `"start" \| "move" \| "cancel" \| "end"` | .toast | The phase of a swipe. |
| `data-swipe-direction` | `"left" \| "right" \| "up" \| "down"` | .toast | Where a swiped toast leaves. |
| `data-rich-colors, data-invert, data-dismissible, data-promise, data-styled` | `"true" \| "false"` | .toast | |
| `--offset, --index, --z-index, --initial-height, --swipe-amount-x, --swipe-amount-y` | custom properties | .toast | Layout and swipe offsets for custom styles. |
| `--toast-index, --toast-height, --toast-offset-y, --toast-swipe-movement-x, --toast-swipe-movement-y` | custom properties | .toast | The same numbers under these names too; --toast-frontmost-height on the list. |
| `data-limited, data-starting-style, data-ending-style` | `"true" \| "false"; present` | .toast | Past visibleToasts; before the enter; during the exit. |
| `data-update-key, data-updated` | count; present | .toast | Updates by id; set again on each, so a CSS animation on it replays. |
| `data-anchored, data-side, data-align, data-anchor-hidden` | present; side; align | .toaster-list | An anchored toast's list, as placed against its anchor. |
| `data-behind` | `"true" \| "false"` | .toast-content | Behind the front toast. |
| `data-swipe-ignore` | present | your element | A press on it never starts a swipe; nor does one on a button, link or field. |
## Accessibility
- The region is a `` named "Notifications alt+T": the hotkey is in its name so it can be found.
- Each toast is announced when it appears and when its title or type changes (a promise settling): title, description and the action's altText. important toasts use the assertive live region; others the polite one.
- Each toast is role="status" with aria-live off: named by its title (aria-labelledby) and described by its description (aria-describedby), so a focused toast is read by name; its announcement comes from the live region.
- Toasts never take focus on their own. The hotkey moves focus into the region; Tab past the last toast, or Escape on the region, returns it.
- Timers pause while the pointer is over the stack, while keyboard focus is in it, while a toast is pressed (a press released off the stack lets it go), while the window is in the background and while the tab is hidden.
- Hidden toasts beyond visibleToasts are inert. The close button has an accessible name; icons are decorative. On a non-dismissible toast the close and cancel buttons are aria-disabled.
- With prefers-reduced-motion, toasts appear, restack and swipe out with no motion.
- The region is a manual popover in the top layer, re-shown when a toast arrives, so toasts draw above dialogs and popovers opened before them. While a native modal dialog is open the region moves into the dialog's panel (still in the top layer), so its toasts are announced from a live region inside the dialog, and the hotkey, Tab, presses, hover and swipes reach them while the dialog stays open. Escape on a toast closes the toast, not the dialog.
## See also
- [Button](button): A button or a link that looks like one, in six variants and four sizes.