Open this component in Storybook
Toasts are short notifications announced to assistive technology without
taking focus. Mount one <dsgn-toaster> per app, then call toast() from
anywhere. The toaster is the only stateful piece. toast() just dispatches a
dsgn-toast event on document.
Usage
<dsgn-toaster
label="Notifications"
dismiss-label="Dismiss notification"
queued-label="+{count} queued"
paused-label="paused"
></dsgn-toaster>
import '@ds-gn/ui/toaster';
import { toast } from '@ds-gn/ui/toast';
toast.success('Changes saved', {
description: 'Token overrides were published.',
});
const id = toast.error('Couldn’t publish', {
description: 'The registry rejected the request.',
actions: [{ label: 'Retry', onClick: retry }],
});
toast.dismiss(id); // or toast.dismiss() for every toast
@ds-gn/ui/toast does not import Lit, so it is safe to import during a server
render, where calls are no-ops. In the browser, calls made before a toaster
connects are held (up to 20) and shown in order once one does.
In React, mount the wrapper once and call toast(). No provider or hook is
needed:
import { Toaster, toast } from '@ds-gn/ui/react';
<Toaster label="Notifications" dismissLabel="Dismiss notification" />;
toast.info('Sync started');
Playground
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| max-visible | number | 3 | maxVisible. Timed toasts shown at once before the rest queue. Persistent toasts don’t count. |
| label | string | '' | Accessible name for the region, e.g. “Notifications”. |
| dismiss-label | string | '' | dismissLabel. Accessible name for each dismiss button. Required for an accessible button. |
| queued-label | string | '' | queuedLabel. Pill text while toasts wait; {count} is replaced. Empty shows just “+N”. |
| paused-label | string | '' | pausedLabel. Added to the pill while timers are paused. |
| surface | 'light' | 'dark' | 'light' | Semantic token surface to use. |
Toast options
interface ToastOptions {
title: string;
description?: string; // newlines start a new line
variant?: 'info' | 'success' | 'warning' | 'error'; // default 'info'
duration?: number; // ms; 0 persists. Defaults: 5000, 5000, 7000, 0 (error)
actions?: {
label: string;
onClick?(): void;
appearance?: 'primary' | 'secondary';
}[]; // up to 2
links?: {
label: string;
href?: string;
target?: '_blank' | '_self'; // with href; '_blank' adds rel="noopener"
onClick?(): void;
}[];
icon?: string; // a registered icon name in place of the variant's
onDismiss?(reason: 'timeout' | 'close' | 'action' | 'programmatic'): void;
}
The toast helpers are toast(options), toast.info | success | warning | error(title, options?), which return the toast’s id, and toast.dismiss(id?).
Slots
This component has no slots.
CSS parts
| Part | Description |
|---|---|
region | The labelled notification region. |
queue | The “+N queued” pill. |
list | The stack of toasts. |
toast | Each toast’s surface. |
icon | A toast’s variant icon. |
title | A toast’s title. |
description | A toast’s description. |
links | A toast’s row of links. |
actions | A toast’s row of actions. |
action | Each action button. |
dismiss | The dismiss button. |
progress | The time-remaining bar. |
Events
| Event | Detail | Description |
|---|---|---|
dsgn-dismiss | { id, reason } | Fired when a toast is dismissed. reason is timeout, close, action or programmatic. React: onDsgnDismiss. |
Methods
| Method | Description |
|---|---|
show(options) | Show a toast on this toaster and return its id. |
dismiss(id?) | Dismiss one toast, or every toast (shown and queued). |
Behaviour
- Queue. Up to
max-visibletimed toasts show at once. More wait first in, first out, and their timers don’t start until they show. Errors and anyduration: 0toast skip the queue and don’t count toward the limit, so a pile of errors can never stall it. - Pause. Hovering or focusing anywhere in the region pauses every timer, fans the collapsed stack out, and greys the progress bars.
- Top layer. The region is a
popover="manual"element fixed to the bottom-end corner. A modal dialog makes everything outside it inert, so while a<dsgn-modal>is open the region moves into it and stays reachable. Other native modal dialogs are not handled.
Accessibility
- Both live regions,
role="status"(polite) androle="alert"(assertive, errors only), exist as soon as the toaster connects. A toast is announced as “Title. Description.” when it becomes visible, not when it is queued. - Toasts never take focus. Dismissing the focused toast moves focus to the
next toast’s dismiss button, or to the region, never to
<body>. - Dismiss and action buttons are 32px but get a 44px hit area on touch screens.
- Motion runs through
@ds-gn/motion; underprefers-reduced-motion: reducetoasts fade without moving and the stack jumps into place.