Toast
Confirms an action or reports an event.
Kind
defaultdefault
success
warn
fail
loading
States
held
timer running
loading
Usage
When to use it
- Use
- The result of what the person just did is not visible where they are: copied, published.
- Use
- A background event finished or changed: an eval passed, a sync fell behind.
- Use
- An action can be undone for a short time: archive with Undo.
- Not for
- The person must decide before going on. Use Dialog.
- Not for
- The message must stay until its cause is fixed. Put it on the page.
- Not for
- A form field is wrong. Say so under the field.
Rules
8 rules
- Must
- Give a toast at most one action, through the action option; never put buttons in the title or description. Because a toast is a line that leaves on a timer, and two choices in it ask for a decision it cannot wait for.
- Must
- Report a failure with toast.fail, never toast() with failure words. Because a plain toast() times out and waits behind the limit, while toast.fail stays until closed and always shows.
- Must
- Leave timeout unset so the reading time applies; pass timeout: 0 only to hold a toast. Because a fixed 3000ms takes the toast away before the person reads it and decides on Undo.
- Must
- Mount one Toaster at the app root and call toast() from anywhere. Because every Toaster reads the same manager, so two mounted Toasters show each toast twice.
- Must
- Use toast.promise, or reuse the id with toast.update, when work finishes later. Because toast.loading never times out, so a separate success toast leaves "Running eval" on screen beside "Eval passed".
- Must
- Make a toast's action reachable in the view too, such as Undo in the row's menu. Because the toast leaves on its timer, and a keyboard or screen reader user may never reach its button.
- Never
- Toast after a change already on screen; toast only when the result is out of view. Because a toast for what the person can see teaches them to ignore the stack, including the failure that matters.
- Should
- Write a success title in the past tense with its object, under 48 characters: 'Published refund-prompt v14'.
State order
5 states, highest first
- 1
- fail
- 2
- loading
- 3
- warn
- 4
- success
- 5
- default
Accessibility
4 checks
- The stack is a live region named Notifications; a fail toast is announced assertively, the rest politely.
- Status is a coloured mark and a title that says it; the colour never stands alone.
- F6 moves focus into the stack; the timer and the drain line stop while focus or the pointer is in it.
- The close button is named Dismiss; the action is a real button.
Keyboard
3 keys
- F6
- Moves focus into the toast stack.
- Tab
- Moves between a toast's action and its Dismiss.
- Escape
- Closes the focused toast.
Edge cases
6 edge cases
- A 120-character title
- Wraps; the reading time grows with it, up to 12 seconds.
- Five toasts at once
- Three show; the newest routine one waits with its timer stopped; a fail always shows.
- Phone, 390 wide
- The stack spans the width 16px in and clears the home indicator; a swipe down dismisses.
- A narrow stack
- The action drops under the text, and the X keeps the first line.
- Window in the background
- The timer and the drain line pause until it comes back.
- Reduced motion
- No slide and no drain line; the toast still leaves on time.
API
7 props
toast(title, options)(ReactNode, ToastOptions) => idtoast.promise(promise, labels){loading, success, fail}toast.update(id, kind, title, options)replaces in placetoast.dismiss(id?)(string?) => voidoptions description, action, id, onCloseReactNode, {label, onClick}, string, () => voidoptions timeoutnumberdefaultreading timeToaster limit, inline, managernumber, boolean, managerdefault3, false
Tokens
16 tokens
--paper- #ffffff
--line- rgb(5 5 5 / 0.10)
--line-control- rgb(5 5 5 / 0.15)
--radius-overlay- 10px
--toast- 360px
--space-4- 16px
--ok- #2c9a59
--warn- #d98a0b
--fail- #e35e49
--type-label- 500 13px/1.35 var(--font-sans)
--type-body-sm- 400 13px/1.5 var(--font-sans)
--text-1- rgb(5 5 5 / 0.80)
--text-2- rgb(5 5 5 / 0.60)
--z-overlay- 50
--dur-overlay- 200ms
--ease-out- cubic-bezier(0.2, 0.8, 0.2, 1)