Toast
A line in a corner that says something just happened. It asks for nothing, offers at most one way back, and leaves.
Try it
Rest the pointer on one and its clock stops. Press F6 to move the focus to the newest, and Esc to dismiss it and go back to where you were.
Choosing a toast
A toast is for what has already happened. It appears away from where the reader is looking and it goes on its own, so nothing they cannot do without belongs in it, and its action is never the only way to that action: the undo it offers is also in the page, or the thing can simply be done again.
| When | Use |
|---|---|
| Something the reader just did has happened, and they can go on | Toast |
| It concerns a part of the page and stays true while they look at it | An inline alert, beside that part |
| A field is wrong | The Field’s own error, under the field |
| They must decide before anything else | Dialog |
Anatomy
| Part | Value |
|---|---|
| Least height | 48 |
| Width | 288 to 360; the message wraps |
| Padding | 16 before, 8 after, 8 block |
| Radius | 12 |
| Text, Medium | 14 / 22 |
| Icon | 20 |
| Close and action | 32 tall, radius 8 |
| From the viewport | 24 |
| Between toasts | 8 |
A message, at most one action, and a close that is always there. No title and no second line: what needs those is an alert or a dialog. 3 show at once, the newest nearest the edge, and the rest wait their turn. Under 480 wide every placement becomes the bottom edge, the width of the screen.
The inverse surface, and no colour
The Tooltip sits on the overlay surface, the menu’s, and the toast does not. A tooltip opens where the reader is already looking and can be quiet. A toast opens in a corner they are not looking at and has to be seen: the inverse surface is 15:1 or more against anything it floats over, in both modes.
The tone is read from the shape of the icon, and said in words to a screen reader. It has no colour yet. The theme has text and a border for the inverse surface and nothing else, and the status colours were chosen against light surfaces in light: success green on this near-black does not read. When the theme has status tokens for this surface the icon takes them, and nothing in the API moves.
Hover and pressed are the theme’s own wash, which lightens this surface in light and darkens it in dark, a surface step each way. The focus ring is the text’s colour: in dark this surface is a near-white block, and the focus colour is 1.64:1 on it.
Time
| Toast | Stays |
|---|---|
| A message | 5s |
| A message with an action | 10s |
| An error | Until dismissed |
The clock stops while the pointer is over the toasts, while the focus is among them, and while the tab is in the background, and starts again from the whole duration. A toast raised again with the id of one that is showing updates it in place: “Uploading” becomes “Uploaded” without a second toast.
Accessibility
The Toaster is a named region that is in the page, empty, from the start, holding a polite live list: a screen reader is already listening when the first toast is put there. An error is also an alert, so it interrupts. F6 moves the focus to the newest toast, Tab reaches its buttons, and Esc dismisses it and gives the focus back.
It lives in the top layer as a manual popover: no z-index and no portal, and it is raised again whenever toasts begin, so it sits above a menu or a dialog opened since. One limit is the platform’s. A modal dialog makes everything outside it inert, the top layer included, so a toast raised while a Dialog is open is drawn above it and can be neither pressed nor heard. Say it inside the Dialog, or close the Dialog first.
Using it
import { Toaster, toast } from 'alpenglow';
// Once, near the root.
<Toaster />
// From anywhere, a component or not.
const id = toast('Appointment deleted', {
tone: 'success',
action: { label: 'Undo', onClick: restore },
});
toast.dismiss(id);| Option | Type | Default |
|---|---|---|
message | string | required |
tone | 'neutral' | 'success' | 'danger' | 'warning' | 'info' | 'neutral' |
action | { label: string; on | — |
duration | number, or Infinity | by tone and action |
id | string | generated |
| Prop | Type | Default |
|---|---|---|
placement | 'top-start' | 'top-center' | 'top-end' | 'bottom-start' | 'bottom-center' | 'bottom-end' | 'bottom-end' |
label | string | 'Notifications' |
closeLabel | string | 'Dismiss' |
className | string | — |