Skip to content

Toast

FeedbackSince 0.2.0
import { Toaster, toast } from '@absoluteui/components/toast';
import '@absoluteui/components/toast/style.css';

Using Angular? See Toast for Angular.

Transient notifications, stacked in a labelled region. A Toaster owns one region: a <section aria-label="Notifications"> rendered in the top layer with popover="manual" while it has toasts. The toast() function uses a lazily created default toaster for the document.

AbsoluteUI adds:

  • one announcement per toast through the shared live regions: polite for info and success, assertive for warning and error;
  • no focus stealing;
  • timers that pause on hover and focus (WCAG 2.2.1), with error toasts persistent by default;
  • a hotkey (default Alt+T) that reaches the newest toast, and Escape to dismiss it;
  • a first-in, first-out queue beyond max visible toasts.
  • Confirmation of a completed background action (saved, sent, copied).
  • Non-blocking notices with at most one follow-up action, such as Undo.
  • Errors from background work, which persist until dismissed by default.
  • Information the user must not miss or must act on: use Alert or Dialog.
  • Field validation errors: show them at the field and in the Error Summary.
  • Status tied to a specific place on the page: use Inline Message.
  • Long or rich content: toasts are text only with one action.
import { toast } from '@absoluteui/components/toast';
toast({ tone: 'success', message: 'Changes saved.' });
import { Toaster, type ToastCloseDetail } from '@absoluteui/components/toast';
const toaster = Toaster.create({ position: 'bottom-center', max: 2 });
let restored = false;
const handle = toaster.show({
message: 'Conversation archived.',
action: {
label: 'Undo',
onAction: () => {
restored = true;
},
},
});
toaster.element.addEventListener('aui-close', (event) => {
const { id, reason } = (event as CustomEvent<ToastCloseDetail>).detail;
if (id === handle.id && reason !== 'action' && !restored) {
// archive is final
}
});
const upload = toaster.show({ message: 'Uploading report.pdf', duration: 0 });
upload.update({ tone: 'success', message: 'Uploaded report.pdf', duration: 5000 });
import { Toaster } from '@absoluteui/components/toast';
import '@absoluteui/components/button/style.css';
import '@absoluteui/components/toast/style.css';
const toaster = Toaster.create({ position: 'top-end' });
document.querySelector('#archive')?.addEventListener('click', () => {
toaster.show({
message: 'Conversation archived.',
action: {
label: 'Undo',
onAction: () => {
document.querySelector('#restore')?.dispatchEvent(new Event('click'));
},
},
});
});
import { toast } from '@absoluteui/components/toast';
const upload = toast({ message: 'Uploading report.pdf', duration: 0 });
upload.update({ tone: 'success', message: 'Uploaded report.pdf', duration: 5000 });
toast({ tone: 'error', title: 'Sync failed', message: 'Changes will be retried.' });
<section class="aui-toaster aui-toaster--{position}" aria-label="Notifications" popover="manual">
<ol class="aui-toaster__list">
<li class="aui-toaster__item">
<div class="aui-toast aui-toast--{tone}" role="group" tabindex="-1" aria-labelledby="{id}-text">
<span class="aui-toast__icon">icon (aria-hidden)</span>
<div class="aui-toast__text" id="{id}-text">
<span class="aui-toast__tone">Error: (visually hidden)</span>
<p class="aui-toast__title">title</p>
<p class="aui-toast__message">message</p>
</div>
<div class="aui-toast__actions"><button class="aui-button">Undo</button></div>
<button class="aui-button aui-toast__dismiss" aria-label="Dismiss notification">icon</button>
</div>
</li>
</ol>
</section>
Toaster.create(options?: ToasterOptions, doc?: Document): Toaster; toast(options: ToastOptions, doc?: Document): ToastHandle

Global configuration key: toast (see Configuration).

Option Type Default Description
icons Partial<ToastIcons> Toaster option: icon slot overrides.
position 'bottom-end' | 'bottom-start' | 'top-end' | 'top-start' | 'top-center' | 'bottom-center' "bottom-end" Region corner (logical: end is right in LTR, left in RTL). Globally configurable.
max number 3 Maximum visible toasts (1..20); further toasts queue first-in, first-out. Globally configurable.
duration number 5000 Auto-dismiss delay in ms (0 = persistent). Error toasts persist unless given a duration. Applies to toasts shown afterwards. Globally configurable.
hotkey string | null "Alt+T" Moves focus to the newest toast; null disables. Globally configurable.
locale string "en-US" Locale of the region label, tone prefixes, and dismiss label. Globally configurable. Inherited from common configuration.
Property Type Description
element HTMLElement The region <section>; aui-open and aui-close fire here.
count number Visible toasts.
queued number Toasts waiting for a free slot.
options Readonly<ToasterOptions> Current toaster options.
Method Description
show(options: ToastOptions): ToastHandle Show (or queue) a toast { tone?, title?, message, duration?, action? }. Returns { id, dismiss(), update() }.
clear(): void Dismiss all visible toasts and drop the queue.
update(options: Partial<ToasterOptions>): void Merge and apply toaster options.
destroy(): void Remove the region, timers, listeners, and subscriptions (no events).
dismiss(): void Close the toast (reason programmatic) or drop it from the queue.
update(options: Partial<ToastOptions>): void Merge options; a visible toast is re-announced and its timer restarts.
toast(options: ToastOptions, doc?: Document): ToastHandle Show a toast in a lazily created default Toaster for the document.
Event Detail Bubbles Cancelable Description
aui-open { id: string } No No A toast became visible (fired on the region).
aui-close { id: string; reason: 'timeout' | 'dismiss' | 'action' | 'programmatic' } No No A visible toast closed (fired on the region).

All rules live in the aui.components cascade layer, so application styles override them without specificity battles.

Class Purpose
aui-toaster Region <section> (manual popover).
aui-toaster--bottom-end | --bottom-start | --top-end | --top-start | --top-center | --bottom-center Position modifiers.
aui-toaster__list Ordered list of toasts.
aui-toaster__item List item wrapping one toast.
aui-toast Toast (role=group, tabindex=-1).
aui-toast--info | --success | --warning | --error Tone modifiers.
aui-toast__icon Tone icon (decorative).
aui-toast__text Tone prefix, title, and message; labels the toast.
aui-toast__tone Visually hidden tone prefix.
aui-toast__title Title.
aui-toast__message Message.
aui-toast__actions Action button container.
aui-toast__dismiss Dismiss button.
Slot Default icon
info info
success check-circle
warning alert-triangle
error alert-circle
dismiss close

Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.

--aui-border-width | --aui-border-width-strong | --aui-color-error-fg | --aui-color-error-subtle | --aui-color-focus-ring | --aui-color-info-fg | --aui-color-info-subtle | --aui-color-success-fg | --aui-color-success-subtle | --aui-color-surface | --aui-color-text | --aui-color-warning-fg | --aui-color-warning-subtle | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-sm | --aui-font-weight-semibold | --aui-icon-size-md | --aui-line-height-normal | --aui-radius-md | --aui-shadow-md | --aui-space-1 | --aui-space-2 | --aui-space-3 | --aui-space-4 | --aui-toast-width

type ToastTone = 'info' | 'success' | 'warning' | 'error';
type ToastPosition = 'bottom-end' | 'bottom-start' | 'top-end' | 'top-start' | 'top-center' | 'bottom-center';
type ToastCloseReason = 'timeout' | 'dismiss' | 'action' | 'programmatic';
interface ToastAction { label: string; onAction?: () => void }
interface ToastOptions { tone?: ToastTone; title?: string; message: string; duration?: number; action?: ToastAction }
interface ToastHandle { readonly id: string; dismiss(): void; update(options: Partial<ToastOptions>): void }
interface ToastIcons { info: IconRef; success: IconRef; warning: IconRef; error: IconRef; dismiss: IconRef }
interface ToasterOptions {
position?: ToastPosition;
max?: number;
duration?: number;
hotkey?: string | null;
locale?: string;
icons?: Partial<ToastIcons>;
}
interface ToastOpenDetail { id: string }
interface ToastCloseDetail { id: string; reason: ToastCloseReason }
declare function toast(options: ToastOptions, doc?: Document): ToastHandle;

Pattern: Notification region (labelled section landmark) with announcements through shared visually hidden live regions (WCAG 4.1.3); toasts are not live regions themselves, to avoid double announcements.

Key Context Action
Alt+T (configurable hotkey) Anywhere, toasts visible Moves focus to the newest toast; timers pause while focus is inside.
Tab / Shift+Tab Focus in a toast Moves through the action and dismiss buttons and between toasts.
Escape Focus in a toast Dismisses that toast and returns focus to where it was before entering the region.
Enter / Space Action button focused Runs onAction, then closes the toast (reason action).
Enter / Space Dismiss button focused Closes the toast (reason dismiss) and returns focus.
Element Role
<section class=aui-toaster> region (named ‘Notifications’)
<ol> list
toast group, labelled by its text
icon none (aria-hidden=true)
action and dismiss buttons button (native)
Attribute Element Value
aria-label region Localized ‘Notifications’
aria-labelledby toast id of the text block (tone prefix, title, message)
aria-label dismiss button Localized ‘Dismiss notification’
aria-live shared live regions (announce()) polite for info/success, assertive for warning/error

Toasts never take focus on their own. The hotkey focuses the newest toast (tabindex=-1, visible focus ring). When a focused toast closes, focus returns to the element focused before entering the region, else to the newest remaining toast.

Criterion Level Note
1.3.1 Info and Relationships A
1.3.2 Meaningful Sequence A
1.4.1 Use of Color A
1.4.3 Contrast (Minimum) AA
1.4.11 Non-text Contrast AA
1.4.13 Content on Hover or Focus AA
2.1.1 Keyboard A
2.2.1 Timing Adjustable A
2.4.3 Focus Order A
2.4.7 Focus Visible AA
4.1.2 Name, Role, Value A
4.1.3 Status Messages AA

Automated test results: Accessibility and compliance.

  • Timers pause while the pointer is over the region or focus is inside it (WCAG 2.2.1); error toasts persist until dismissed by default.
  • Tone is conveyed by an icon and a visually hidden, localized prefix, never by color alone; the prefix is part of the announcement.
  • DOM order matches visual order (newest nearest the viewport edge).
  • While a modal dialog is open, the region moves inside it so new toasts are above the dialog and not inert.
  • Announcements use the shared live regions in document.body, which are outside an open modal dialog; screen readers may not announce toasts while a modal is open.
  • Manual screen-reader verification (NVDA, JAWS, VoiceOver) is pending.

Region: hidden (no toasts) or open. Toast: queued, visible, timer running, timer paused (hover or focus), persistent.

From Trigger To
- show() with a free slot visible (announced, aui-open)
- show() with max visible queued
queued a visible toast closes visible
visible timer elapses closed (timeout)
visible pointer over region / focus inside timer paused, resumes with remaining time
visible dismiss button / Escape closed (dismiss), focus returned
visible action button onAction(), then closed (action)
visible handle.dismiss() / clear() closed (programmatic)
  • Toasts never take focus; users reach them with the hotkey, or by Tab (the region follows page content in DOM order). Tell users about the hotkey, for example in your keyboard help.
  • Timers pause while the pointer is over the region or focus is inside it. Errors persist unless given a duration. Keep durations of at least 5 seconds.
  • DOM order matches visual order: the newest toast is nearest the viewport edge.
  • While a modal dialog is open, everything outside it is inert. The region therefore moves into the open modal dialog when a toast is shown, and back to document.body when that dialog closes, so toasts stay above the dialog and remain operable.
  • The shared live regions used by announce() are in document.body. While a modal dialog is open they are outside the dialog, so screen readers may not announce toasts (see section 30).
  • The e2e axe run (WCAG 2.2 AA, 3 themes) and manual screen-reader verification are pending.

Region width is min(toast-width, 100vw - 2rem), pinned space-4 from the configured edges or centred. Text wraps.

Positions use logical insets: end is the right edge in LTR and the left edge in RTL. Icon and border sit at the inline start.

An opaque color-surface background under a color-{tone}-subtle tint (matching the contrast gate’s backdrop), color-{tone}-fg icon and border, color-text text, and shadow-md. Forced-colors mode removes the tint and uses CanvasText borders. The entry slide/fade uses @starting-style and is removed under prefers-reduced-motion or animation: 'none'.

configureAbsoluteUI({ components: { toast: { position: 'top-end', max: 4, duration: 8000, hotkey: 'Alt+N' } } });

Toaster.create(options) and toaster.update(options) override global and theme defaults; per-toast duration overrides both. All options are dynamic. Changing duration affects toasts shown afterwards; changing max reveals queued toasts at once.

icons.info (default info), icons.success (check-circle), icons.warning (alert-triangle), icons.error (alert-circle), icons.dismiss (close), set per toaster.

Title, message, and action label use textContent; they are never parsed as HTML. No inline styles (the visually hidden prefix uses the CSSOM). CSP-safe.

No persistence, network access, or telemetry. Message text is copied into the shared live regions for announcement.

Constant work per toast; at most max toasts are in the DOM. One document keydown listener per toaster, for the hotkey.

max up to 20 visible toasts. The queue is unbounded; avoid producing toasts in loops.

  • Focus inside a toast that closes (Escape, dismiss, action, or timeout) returns to the element focused before entering the region. If that element is gone, focus moves to the newest remaining toast.
  • A toast shown while the region is hovered or focused starts its timer only after the pointer leaves and focus leaves.
  • Toasts already visible when a modal dialog opens stay beneath it until the next toast is shown.
  • If the region is removed from the DOM by other code, toast() creates a new default toaster.
  • show() after destroy() throws TOASTER_DESTROYED. Handles of closed toasts are inert.
Code Category Cause
TOAST_OPTIONS configuration Missing or blank message, unknown tone, invalid duration, or invalid action.
TOASTER_DESTROYED runtime show() on a destroyed toaster.
ICON_UNKNOWN configuration Unknown icon override.
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION configuration Invalid or unknown configuration (e.g. max: 0).

Invalid toaster options throw before the region is appended; invalid toast options throw before anything is shown.

  • Announcements while a modal dialog is open depend on the shared live regions, which sit outside the dialog (planned fix in @absoluteui/utilities).
  • There is no exit animation; toasts are removed immediately.
  • matchesHotkey compares event.key. On macOS, Option+letter produces a different character, so Alt+T may not match there; configure another hotkey.
  • Manual screen-reader verification is pending.
  • HTML or Node content.
  • More than one action per toast.
  • Swipe-to-dismiss gestures.