Skip to content

Toaster

Not yet released

The rewritten Toaster is not yet released. This page documents the upcoming component — APIs and behavior described here may change before release.

Overview

The toaster is the Beacon notification system for AJAX/action outcomes. It has two surfaces:

  • Result toasts: success, error, warning, info and loading states for the outcome of an action. Rendered by EnToaster.
  • Notices: quiet, momentary feedback pills like "Copied to clipboard", with an optional Undo. Rendered by EnNotice.

Unlike most components in this library, you don't interact with the Vue components directly. They have no props, slots or events; EnToaster and EnNotice are pure renderers of a shared store, and the entire API lives in the useToaster() composable. Notifications can be fired from anywhere: components, stores, or plain JS modules.

The store is pinned to window, so every bundle on the page (and every non-Vue caller) shares a single toast stack. This is also what powers the legacy window.Toaster adapter.

Setup

For basic use, no setup or imports are needed. The shared instance is bound to the global notifier, so existing patterns keep working as-is:

js
window.Toaster.showSuccess('Your changes have been saved.', 4000);

To go beyond the basics (typed results, handles, notices, configuration), import the composable:

js
import { useToaster } from '@front-end/en-components';

const toaster = useToaster();
toaster.success({ title: 'Saved', message: 'Coverage is effective May 1, 2026.' });

useToaster() returns the same shared instance on every call, in every bundle. It is the same object bound to window.Toaster, so it's safe to call wherever you need it rather than passing the instance around.

App setup (once per app)

The render components are mounted a single time near the root of the app, alongside the global binding. Within Navigator this is handled for you; only new or standalone apps need to wire it up:

html
<EnToaster />
<EnNotice />
js
import { useToaster } from '@front-end/en-components';
window.Toaster = useToaster();

Demos on this page

This page mounts <EnToaster /> and <EnNotice /> once at the top, exactly as an app would. In the editable examples below, toaster is the object returned by useToaster().

Result toasts

The severity methods success, error, warning, info and loading are shorthand for show({ ...options, type }). Success/info/warning auto-dismiss with a hover-pausable countdown; errors and loading persist until dismissed.

Loading → result

Every show() call (and the severity shorthands) returns a handle. Use resolve() to morph a toast in place, for example a loading spinner into a success, preserving its position in the stack so it doesn't jump.

Actions and details

Toasts can carry action buttons and a collapsible drawer for raw server detail. When details is present, a Copy error action is added automatically.

Notices

For quiet confirmations that don't need a title or a close button, use notice(). copied(thing) is a shorthand for the common clipboard flow, and passing an undo callback adds an Undo button.

API reference

show(options)ToastHandle

Shows a result toast. Honors the visible-stack cap (maxVisible, default 4); excess toasts queue and appear as slots free up. The severity shorthand methods take the same options object:

js
toaster.show({ type: 'success', title: 'Saved' });
toaster.success({ title: 'Saved' }); // equivalent

ToastOptions

OptionTypeDefaultDescription
type'success' | 'error' | 'warning' | 'info' | 'loading''info'Severity. 'spinner' is accepted as an alias of 'loading'.
titlestringBold heading line.
messagestringConvenience single body line; appended to lines.
linesArray<string | { text } | { html }>Body line items. Strings/text render escaped (XSS-safe); { html } items are opt-in and must be pre-sanitized by the caller.
htmlbooleanfalseTreat message as pre-sanitized HTML.
detailsstringRaw server payload shown in a collapsible drawer. Auto-adds a Copy error action.
actionsToastAction[]Action buttons (see below).
iconstringper typeOverride the default severity icon (icomoon class).
durationnumberper typeAuto-dismiss in ms; 0 persists. Defaults: success 5000, info 6000, warning 8000, error 0, loading 0.
dismissiblebooleantrueShow the close button.

ToastAction

OptionTypeDefaultDescription
labelstringButton text.
onClickfunctionClick handler; receives the toast object.
variant'primary' | 'ghost''primary'Button tone (ghost renders btn-secondary).
iconstringLeading icomoon class, e.g. 'icon-redo'.
closebooleantrueDismiss the toast after the action runs.

ToastHandle

MemberDescription
idThe toast's id.
update({ title?, message? })Patch the live toast's title/message.
resolve(type, options?)Morph the toast in place (e.g. loadingsuccess), keeping its id and stack position. Returns the handle.
dismiss()Dismiss the toast.

notice(text, options?)NoticeHandle

Shows a lightweight feedback pill. No title, no close button, auto-dismisses.

OptionTypeDefaultDescription
iconstring'icon-check-circle-solid'Leading icomoon class.
undofunctionWhen provided, an Undo button is shown that calls this and dismisses.
durationnumber2200Auto-dismiss in ms.

The handle exposes a single dismiss() method.

copied(thing, options?)NoticeHandle

Shorthand for clipboard flows. Shows "<thing> copied to clipboard" with the copy icon.

setDefaults(patch) / configure(patch)

Merges app-level defaults. durations is deep-merged; all other keys are replaced.

KeyTypeDefaultDescription
placement'top-center' | 'top-right' | 'bottom-right' | 'top-left''top-center'Toast region position.
accent'medallion' | 'rail' | 'plain''medallion'Severity accent style.
density'comfortable' | 'compact''comfortable'Toast sizing.
progressbooleantrueShow the countdown bar on auto-dismissing toasts.
maxVisiblenumber4Visible-stack cap before toasts queue.
loadingDelaynumber150Ms a legacy showSpinner() waits before appearing; if the action resolves/hides first, no spinner shows. 0 shows immediately. (Does not affect the modern loading() API.)
loadingMinVisiblenumber500Once a showSpinner() is shown, the min ms it stays before it can morph — so it can't flash on and off.
durationsobjectsee abovePer-type auto-dismiss ms (0 persists).
noticePlacement'bottom-center' | 'bottom-right''bottom-center'Notice region position.
noticeTheme'light' | 'dark''light'Notice pill theme.
noticeDurationnumber2200Notice auto-dismiss ms.

Other methods

MethodDescription
dismissAll()Clear everything immediately: visible toasts, the queue, and all notices.
dismissToast(id) / dismissNotice(id)Dismiss a single toast/notice by id (the handles wrap these).
copyText(text)Copy text to the clipboard (async API with a synchronous fallback; best-effort).
promise(p, { loading?, success?, error? })Drive a spinner → result from a promise: shows the (deferred) spinner, then morphs it to a success or error when p settles. success/error may be strings or functions of the resolved value / rejection. Resolves or rejects through to the caller. Because the spinner is deferred, fast work shows only the result with no spinner flash.

Legacy window.Toaster

The object returned by useToaster() is also a drop-in replacement for the legacy global notifier. It is bound once at app startup, and the existing call sites keep working unchanged:

js
import { useToaster } from '@front-end/en-components';
window.Toaster = useToaster();

The legacy surface is single-message: each show* call replaces the current toast, except spinner → result, which morphs in place. Auto-hide applies only when an explicit ms is passed; errors and the spinner always persist.

To avoid flicker on fast actions, showSpinner() is deferred by loadingDelay ms (default 150) — if the work finishes first, no spinner ever appears — and once shown it stays at least loadingMinVisible ms (default 500) before morphing. So most quick saves show only the result, and a spinner that does appear can't blink in and out. The modern loading() API is unaffected and shows immediately. Both timings are configurable via setDefaults (set loadingDelay: 0 to disable the deferral).

Legacy methodBehaviorModern equivalent
showError(message)Replaces the current toast with a persistent error.toaster.error({ message })
showSuccess(message, ms?)Success toast; with ms it auto-hides and the returned Promise resolves on dismiss.toaster.success({ message, duration })
showWarning(message, ms?)Warning toast; same Promise contract as showSuccess.toaster.warning({ message, duration })
showErrorModel(model, hidePropertyNames?)Renders a validation model's Errors[], one line per entry, as "<ErrorMessage> (<PropertyName>)". The (<PropertyName>) is omitted when an entry has no property name.toaster.error({ lines })
showSuccessModel(model, ms?)Renders a success model's Messages[], one line each.toaster.success({ lines, duration })
showErrorGeneric()The fixed generic "An error occurred…" message.
showSpinner(altMessage?)Loading state, deferred by loadingDelay (see note above); persists until hidden or morphed by the next showSuccess/showError.toaster.loading({ title }) + handle.resolve()
hideSpinner() / hideError() / hideSuccess() / hideWarning()Hide the current toast if it matches that type.handle.dismiss()
hide()Clear everything.toaster.dismissAll()
addError(message)Append a line to the current error toast (or start one).