Toast
A toast is a short message that confirms an action, floats at the bottom of the screen, and goes away on its own.
<tk-button onclick="document.querySelector('tk-toaster').toast('Changes saved')">Save changes</tk-button>
<tk-toaster></tk-toaster>Anatomy
| Part | What it is |
|---|---|
tk-toaster |
the region you add once; it places, queues, and announces toasts |
tk-toast |
the pill the toaster creates for each message |
| message | one short line of text |
| action | one optional button, such as Undo |
| dismiss button | the ✕, only with dismissible |
There is one look: a dark pill in the light theme and a light one in the dark theme. There are no tones and no icons.
Show a toast
Add one empty tk-toaster to the page, then call toast() on it.
<tk-toaster></tk-toaster>
<tk-button onclick="document.querySelector('tk-toaster').toast('Changes saved')">Save changes</tk-button>- Put the toaster in your page markup, empty, before any toast. Screen readers only announce a live region that already existed, so don't create it the moment you need it.
- Use one toaster per page.
Actions
const toaster = document.querySelector('tk-toaster');
toaster.toast('Conversation archived', {
action: {
label: 'Undo',
handler: () => restoreConversation(),
altText: 'Undo: press {hotkey} then Enter',
},
});- One action at most, and only as a shortcut. The user must be able to do the same thing somewhere else on the page. If the action is the only way, use a dialog.
altTextis required with an action. Screen readers hear it after the message, so say how to reach the action.{hotkey}becomes the toaster's hotkey, F8 by default.dismissible: trueadds a ✕. Most toasts don't need one; they leave on their own.
Behavior
| Toast | Shown for |
|---|---|
| without an action | 5 seconds |
| with an action | at least 10 seconds |
- Hover, focus, and switching windows pause the timer. It resumes with the time that was left.
- Set
durationfor a longer message. Plan about 5 seconds plus 1 second for every 120 words. - One toast shows at a time, in the order they came. The same message twice in a row restarts the current toast instead of queuing a copy.
- Up to 3 wait in the queue (
max-queue). Past that, the oldest waiting toast is dropped. toast()returns a handle. Callhandle.dismiss()to remove the toast early; it's always safe to call.
Before a toast leaves, tk-toaster fires a cancelable tk-dismiss event. Call
preventDefault() to keep it on screen, for example while an undo finishes.
toaster.addEventListener('tk-dismiss', (event) => {
if (event.detail.reason === 'action' && undoInProgress) event.preventDefault();
});Position
The toast floats at the bottom center, above dialogs, 16px from the bottom edge. If you
have a bottom navigation bar, raise --tk-toaster-offset so the toast never covers it.
The empty toaster doesn't block clicks on the page.
When to use
- Use a toast to confirm something that just happened: "Changes saved", "Link copied", "Message sent".
- Never use it for an error or anything urgent. A message that disappears is easy to
miss. Use a
Section message , aBanner , or aDialog . - Use a
Banner for a message about the whole app, such as maintenance. - Use a
Dialog when the user must act before going on. - Keep toasts rare. If the user must see the message, a toast is the wrong place.
Content
- Say what happened, in the past tense: "Changes saved", "Link copied".
- Keep it to one short line. No errors, no urgent wording.
- Use one verb for the action: "Undo", "View".
More in
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
Add one empty tk-toaster in the page markup |
Create the toaster when the first toast fires |
| Confirm a finished action in one short line | Put an error or a warning in a toast |
Offer Undo as a shortcut, with altText |
Make the toast the only way to do something |
Raise --tk-toaster-offset above a bottom bar |
Let a toast cover the navigation |
Set a longer duration for a long message |
Rely on 5 seconds for text that takes longer to read |
Related
Section message : a message that stays in the page content.Banner : a message about the whole app.Dialog : a message that blocks until the user acts.
API
tk-toaster attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
label |
string | "Notifications" |
the region's name; the hotkey is added to it |
hotkey |
string | "F8" |
the key that moves focus into the toast |
max-queue |
number | 3 |
how many toasts can wait |
The read-only pending property counts the toasts waiting.
toast(message, options)
| Option | Type | Default | What it does |
|---|---|---|---|
duration |
number (ms) | 5000, or 10000 with an action |
how long it shows; at least 10000 with an action |
action |
{ label, handler, altText } |
none | one action; altText is required |
dismissible |
boolean | false |
shows the ✕ |
Returns a handle with dismiss().
Events
| Event | What it means |
|---|---|
tk-dismiss |
a toast is about to leave; detail.reason is timeout, dismiss, or action. Cancelable: preventDefault() keeps it (and restarts the timer on timeout) |
CSS
Set these on tk-toaster or any ancestor.
--tk-toaster-offset: the gap from the bottom edge,space-16by default.--tk-toast-max-width: the pill's maximum width,320pxby default.--tk-toast-enter-distance: how far the pill slides in;0, a plain fade, by default.
Tokens
| Part | Token |
|---|---|
| pill | surface/inverse, shadow-2, radius-16 |
| message | text/inverse, Body Medium |
| action | text/inverse, Label Large |
| ✕ | icon/inverse |
| border, high contrast only | border/default |
| focus ring | border/inverse |
| layer | z-toast |
Accessibility
Built in:
- A hidden
role="status"region announces each toast politely. It never interrupts. - The toaster is a named region screen reader users can jump to, and the hotkey (F8) moves focus into the current toast. Esc there dismisses it, and focus goes back where it was.
- A toast never takes focus by itself.
- The pause on hover and focus gives people time to read and act.
- The text is 12.26:1 on the pill, and the ✕ meets 3:1, in every theme.
- With reduced motion, the toast appears and leaves without animating.
Your part:
- Add the toaster once, empty, in the page markup.
- Give every action an
altText, and keep the action a shortcut. - Never use a toast for errors or urgent messages.
- Keep the toast clear of bottom navigation with
--tk-toaster-offset.
Limits
- Actions in a toast are hard to reach for keyboard and screen reader users before the
toast leaves. The hotkey, the pause, and
altTexthelp, but they don't fully meet WCAG. Never make the action the only way to do something. - The ✕ is always named "Dismiss".
toast()has no option to change it.