Skip to content

Toast

Transient notifications announced through an aria-live region. Toasts are imperative — call showToast() to append one:

import { showToast } from "@relements/core/behaviors/toast";
showToast("File saved.");
showToast("Upload complete.", { tone: "success" });
showToast("Could not connect.", { tone: "danger", duration: 8000 });

tone is "default" | "success" | "warning" | "danger"; duration is the auto-dismiss time in ms (0 keeps it until dismissed). With no existing [data-re-toast-region] on the page, showToast creates a region on <body>.

Prefer a declarative tag? The <re-toast> custom element hosts the same region and exposes a .show(message, options) method.

The buttons below fire real toasts (wired with showToast on click):

Live example
<div class="row">
  <button type="button" class="re-button" id="t-default" data-demo-toast="File saved.">
    Default
  </button>
  <button
    type="button"
    class="re-button"
    data-variant="secondary"
    id="t-success"
    data-demo-toast="Upload complete."
    data-demo-toast-tone="success"
  >
    Success
  </button>
  <button
    type="button"
    class="re-button"
    data-variant="danger"
    id="t-danger"
    data-demo-toast="Could not connect."
    data-demo-toast-tone="danger"
  >
    Danger
  </button>
  <button
    type="button"
    class="re-button"
    data-variant="ghost"
    id="t-warning"
    data-demo-toast="Connection unstable."
    data-demo-toast-tone="warning"
  >
    Warning
  </button>
</div>
  • Keyboard — Toasts never steal focus, so nothing is required to read them. Each toast carries a native dismiss <button> (the ×): reach it with Tab, trigger with Enter or Space. There is no roving or Escape model — toasts are not a focus-managed widget.
  • Focus — The dismiss button shows a visible :focus-visible ring (--re-shadow-focus). Toasts appear in a position: fixed region and do not trap or move focus.
  • Semantics — The region is role="region" with aria-label="Notifications"; the toast list is an aria-live region (aria-live="polite", aria-relevant="additions") so screen readers announce each new toast as it is appended. The danger tone uses role="alert" for an interruptive announcement; every other tone uses role="status" (polite). The dismiss button has an aria-label="Dismiss notification" since its label is only the × glyph.
  • Notes — Tone is conveyed by role and live-region politeness, not by colour alone; the tinted background, coloured border, and text all sit on the same themed surface for contrast in light and dark mode. See the accessibility guide for the live-region conventions used across Relements.