Skip to content

Toast

A short, non-blocking message. Persistent until dismissed; announced politely; never takes focus.

  • Free core, MIT
  • Version 2.0.0-rc.1
  • APG pattern: Status live region in a landmark

Examples

These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.

Default

Settings saved

Show the code

Default, code

<Toast title="Settings saved" onDismiss={() => {}} />

Tones

Success: Settings saved

Information: Invite sent to sam@northwind.co.uk

They have 7 days to accept.

Error: Could not save

Check your connection and try again.

Member removed

Show the code

Tones, code

<div className="flex flex-col gap-gap-md">
  <Toast title="Settings saved" tone="success" onDismiss={() => {}} />
  <Toast title="Invite sent to sam@northwind.co.uk" tone="info" description="They have 7 days to accept." onDismiss={() => {}} />
  <Toast title="Could not save" tone="danger" description="Check your connection and try again." onDismiss={() => {}} />
  <Toast title="Member removed" action={{ label: 'Undo', onAction: () => {} }} onDismiss={() => {}} />
</div>

With toaster

Show the code

With toaster, code

const demoQueue = new ToastQueue({ maxVisible: 3 });

function Example() {
  useEffect(() => () => demoQueue.clear(), []);
  return (
    <div>
      <Button onPress={() => demoQueue.add({ title: 'Settings saved', tone: 'success' })}>Save changes</Button>
      <Toaster queue={demoQueue} />
    </div>
  );
}

Collapsed stack

  1. Error: Could not save

    Check your connection and try again.

Show the code

Collapsed stack, code

function Example() {
  const [queue] = useState(() => {
    const q = new ToastQueue({ maxVisible: 3 });
    q.add({ title: 'File uploaded', tone: 'success' });
    q.add({ title: 'Invite sent to sam@northwind.co.uk', tone: 'info' });
    q.add({ title: 'Could not save', tone: 'danger', description: 'Check your connection and try again.' });
    return q;
  });
  return <Toaster queue={queue} stack="collapsed" />;
}

Tokens

The 16 design tokens Toast reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.

Show all 16 tokens
Tokens Toast reads
TokenValue nowCSS variable
color.icon.danger…--sd-color-icon-danger
color.icon.info…--sd-color-icon-info
color.icon.success…--sd-color-icon-success
elevation.1…--sd-elevation-1
elevation.2…--sd-elevation-2
layer.toast…--sd-layer-toast
spacing.gap.md…--sd-spacing-gap-md
spacing.gap.sm…--sd-spacing-gap-sm
spacing.stack.xs…--sd-spacing-stack-xs
toast.bg…--sd-toast-bg
toast.border…--sd-toast-border
toast.fg…--sd-toast-fg
toast.fg-secondary…--sd-toast-fg-secondary
toast.gap…--sd-toast-gap
toast.padding…--sd-toast-padding
toast.radius…--sd-toast-radius

Install

The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).

Install

npm i @superduperui/react @superduperui/tokens

Import

import { Toast, Toaster, toast, toastQueue, ToastQueue } from "@superduperui/react"

Props

Toast also takes the props of the React Aria component it’s built on.

Toast props
PropTypeWhat it does
titlerequiredstring
descriptionstring
toneToastToneDefault 'neutral'
action{ label: string; onAction: () => void }
iconLucideIcon | nullStatus icon. Defaults to the tone's icon (success: CircleCheck, danger: CircleAlert, info: Info; neutral: none). Pass null for no icon.
onDismiss() => voidCalled by the dismiss button. Omit to render without one (static previews only).

When to use it

Use it for

  • Confirming a completed action (Settings saved)
  • Offering undo after a change

Use something else for

  • Errors the user must fix: show them inline
  • Anything that needs a decision: use Dialog

Accessibility

Screen readers announce Polite: "Success: Settings saved".

WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.1.3, 2.3.2, 2.4.13, 2.5.5, 2.5.6, 2.3.3.

Compact density meets AA (2.5.8, 24px targets), not AAA.

What your product still has to do

  • Render one Toaster near the root
  • Keep messages short; never put the only copy of information in a toast

Shared patterns it ships with: 2.2.3 (persistent by default); 2.2.4 (pause notifications pattern); 2.4.12 (publishes its height as scroll padding).

This release’s test results

Test results for Toast in this release
axe-core (WCAG A, AA, AAA and best practice)100 runs across every story, theme, density and width: 0 violations
Rendered text contrast160 text runs: 0 below 7:1, lowest 11.42:1
Target size38 targets: 0 under 44px in Comfortable
Focus appearance (2.4.13)108 focus stops in 3 browser engines: all pass
Keyboard scriptChromium 5 of 5, Firefox 5 of 5, WebKit 5 of 5

Manual passes with VoiceOver and NVDA haven’t been done yet.

Keyboard

Each step is scripted and run in Chromium, Firefox and WebKit.

Toast keyboard steps
KeyWhat happens
TabTab reaches the button
EnterThe toast appears and is announced politely; focus stays where it was
F6F6 moves focus to the notifications region
TabTab reaches the dismiss button
EnterEnter dismisses; focus goes back to where the user came from

In Figma

The Figma component is Toast, with Tone (Neutral, Success, Danger, Info). The Figma library isn’t published yet.

Figma to code: Tone → tone (Neutral = "neutral", Success = "success", Danger = "danger", Info = "info"); Title → title; Description → description when Show description; Status icon → icon when Custom icon; Show dismiss → onDismiss; nested Action → action.label.