Skip to content

Components · Status and feedback

Toast

Transient notifications from useToast(), rendered by ToastProvider.

@rookcom/monarch-reactComponent

Success with undo

    Usage examples

    Errors from an API

    More time for people who need it

    Purpose

    Brief, transient feedback about an action that just happened, with one optional action such as Undo.

    Use when

    • Confirming an action (saved, archived, assigned).
    • Reporting a failure that does not block the page (toast.error).
    • Offering Undo for a reversible action instead of asking for confirmation first.

    Avoid when

    • The message must stay visible: use Alert, InlineNotice or CalloutBanner.
    • The user must decide something: use Dialog.
    • The error belongs to a field: use the Field error.

    Design principles

    • Mount ToastProvider once near the root; call toast() from useToast() anywhere below it.
    • A toast never takes focus; it is announced through a live region and reachable with F8.
    • Danger is announced assertively, everything else politely.
    • Toasts with an action, and danger toasts, stay 10s by default; others 5s. Users can be given more time with durationScale.
    • At most three are open (limit); older ones close first.
    • Never put essential information only in a toast. Errors that block the user belong on the page as well.

    API reference

    import { ToastProvider, getErrorMessage, useToast } from '@rookcom/monarch-react';
    ExportKindRenderingRoot class
    ToastProvidercomponentclient.mn-duration-base
    getErrorMessageutilityclient–
    useToasthookclient–

    toast(options) returns { id, dismiss }. toast.success, toast.error (danger), toast.warning and toast.info take (title, options?).

    dismiss(id) closes one toast; dismiss() closes all.

    useToast() throws outside ToastProvider.

    getErrorMessage(error, { fallback, network }) turns any thrown value into one readable sentence: field errors, message, errors[], detail, from the response body first. Transport messages ("Request failed with status code 500", "Failed to fetch") and HTML error pages are replaced by the fallback.

    Migrating from sonner: toast.success(msg, { action }) and toast.error(msg) have the same shape; action is { label, onClick }.

    Generated from the TypeScript declarations of packages/react/src/components/feedback/toast.

    Properties

    ToastOptions: title, description, tone, action ({ label, onClick, altText }), duration, politeness, onDismiss.

    ToastProvider

    Mount once near the root. Provides `useToast()` and renders the viewport. Toasts never take focus. They pause while hovered or focused, can be reached with F8 (the `hotkey`), and close with Escape. Each one is announced once through a live region: assertively for `danger`, politely otherwise.

    PropTypeDescription
    children requiredReactNode
    dismissLabelstringAccessible name of each toast's close button. Default "Dismiss".
    durationScalenumberMultiplies every auto-dismiss duration (WCAG 2.2.1 Timing Adjustable). Wire it to a user preference: `2` doubles the time, `Infinity` turns auto-dismiss off. Default 1.
    hotkeystring[]Keys that move focus to the toast region, as `KeyboardEvent.code` or modifier names (`['altKey', 'KeyT']`). Default `['F8']`. The hint is added to the region's name ("Notifications (F8)").
    labelstringAccessible name of the toast region, also read before each announcement.
    limitnumberHow many toasts are shown at once; older ones close first. Default 3.
    position"bottom-right" | "bottom-center" | "top-right"Where toasts appear.

    Variants

    PropValuesDescription
    tone'neutral''info''success''warning''danger'Accent edge and icon (none for neutral). Default neutral. Exposed as data-tone.
    politeness'polite''assertive'How it is announced. Default assertive for danger, polite otherwise. Exposed as data-politeness.
    ToastProvider position'bottom-right''bottom-center''top-right'Viewport placement. Default bottom-right. Swipe direction is right for right positions, down otherwise.

    States

    StateExposed asBehaviour
    Opendata-state="open"Visible; auto-dismisses after its duration unless paused.
    Paused–While the pointer is over the region, focus is inside it, or the window is in the background.
    Closeddata-state="closed"Exit animation runs, then the record is removed; onDismiss fires once.
    Swipingdata-swipeFollows the pointer and dismisses at the end of a swipe.

    Interaction behaviour

    • Auto-dismisses after duration (5s; 10s for danger or with an action) times the provider’s durationScale. Infinity on either keeps it until dismissed.
    • Pauses on hover and focus, and resumes when both leave.
    • Activating the action runs onClick and dismisses the toast.
    • The Dismiss button, Escape and a swipe close the toast.

    Keyboard support

    KeysAction
    F8Moves focus to the toast region (configurable with hotkey).
    Tab / Shift+TabMoves between toasts, their action and Dismiss buttons.
    EscapeDismisses the focused toast.

    Focus is never moved to a toast automatically.

    Accessibility

    Role
    region (named, with the hotkey) containing a list; each toast is a list item
    Accessible name
    The region is named by label plus the hotkey ("Notifications (F8)"); each toast by its title.
    • Each toast is announced once through a separate live region: aria-live="assertive" for danger (or politeness="assertive"), polite otherwise. The list items carry no live role, so nothing is announced twice and the list stays valid.
    • Toasts never steal focus (WCAG 2.4.3); F8 reaches them, so the action is keyboard accessible (2.1.1).
    • Timing is adjustable (WCAG 2.2.1): hover or focus pauses, durationScale gives more time or turns auto-dismiss off.
    • The close button is labelled dismissLabel (default "Dismiss") and described by the toast title, so several toasts stay distinguishable.
    • The action announces altText (default its label) so screen-reader users know how else to do it after the toast is gone.
    • Icons are aria-hidden. Reduced motion shortens the enter and exit animations to nothing.

    Responsive behaviour

    • The viewport is min(24rem, 100vw - 2rem) wide, so toasts fit narrow screens down to 320px.

    Theme support

    • Raised surface and tone accent tokens, so light, dark and high-contrast themes apply.
    • Reduced motion shortens the enter and exit animations.

    Do and don't

    Do

    • Keep the description to one line.
    • Offer Undo for reversible actions instead of a confirmation dialog.
    • Pass errors through getErrorMessage so people never see raw server or transport text.
    • Wire durationScale to an accessibility preference if your app has one.

    Don't

    • Do not mount more than one ToastProvider.
    • Do not put essential information only in a toast; it disappears.
    • Do not set politeness="assertive" for confirmations.

    Dependencies

    KindDepends on
    npm packages@radix-ui/react-toastreact
    Monarch componentsNone

    Testing coverage

    • Shows, runs the action (which dismisses) and dismisses with the close button.
    • No axe violations with toasts of every tone open: list items carry no role (regression).
    • Danger is announced assertively and other tones politely; politeness can be overridden.
    • Never moves focus when a toast appears.
    • F8 (or a custom hotkey) moves focus to the named region; Tab reaches the action; Escape dismisses.
    • Each Dismiss button is labelled and described by its toast title.
    • Keeps at most limit open; dismiss() closes all; onDismiss fires once each.
    • Shorthands set the tone; a handle dismisses only its toast.
    • Timing: 5s / 10s defaults, durationScale, Infinity, pause on focus and on hover.
    • The action uses altText for screen readers.
    • getErrorMessage: body before transport text, field errors, lists, fallbacks, network message.
    • useToast throws outside a provider; renders on the server.
    CheckCovered
    Axe in jsdomYes
    Server renderingYes
    Browser suitesCross-browser axe: /components/toast

    Tests: packages/react/src/components/feedback/toast