Toast

Briefly reports an outcome without blocking the page, using an icon to convey tone.

import { Toast } from "@usefragments/ui";Source

Preview

<Toast
  title="Draft saved"
  description="Kept until you publish."
/>

Usage

Use when

  • Confirming an action landed
  • Reporting whether an operation worked
  • News the user does not have to act on
  • Messages that can disappear on their own

Avoid when

  • Errors the user must resolve — use Dialog
  • Anything that must stay on screen — use Alert
  • Field-level validation — use form error states
  • Site-wide notices — use a banner

Implementation notes

  • One sentence, plus a title if it helps
  • Match the tone to what actually happened; most toasts are neutral news
  • Toasts stay at least five seconds and pause while hovered, focused or the window is in the background
  • Three on screen at most; the rest wait in order
  • One verb at most; an undo gets the undo key
  • useToast() returns toast, success, warning, danger, promise, update, dismiss and dismissAll

Installation

pnpm add @usefragments/ui

Import styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.

Anatomy

Import Toast once, then compose its parts with dot notation.

  • Toast.Provider

Examples

Tones

The icon carries the outcome; the plane stays raised.

import { Stack } from '@usefragments/ui';

<Stack direction="column" gap="sm">
  <Toast title="Branch merged" description="Checks passed on main." tone="success" />
  <Toast title="Usage near the limit" description="9 of 10 seats in use." tone="warning" />
  <Toast title="Push failed" description="The remote refused the branch." tone="danger" />

With Undo

One-tap way back from something destructive, with the undo key.

<Toast
  title="Deleted 3 findings"
  action={{ label: 'Undo', onClick: () => {}, undo: true }}
  onDismiss={() => {}}
/>

Busy

Work in progress with a count, a progress line and Stop.

<Toast
  title="Uploading files"
  busy={{ done: 3, total: 12, onStop: () => {} }}
/>

Live

Toast.Provider owns timing and stacking; useToast dispatches.

import { useToast } from "@usefragments/ui";

function SaveButton() {
  const { success } = useToast();
  return <Button onClick={() => success('Draft saved')}>Save</Button>;
}

API reference

Component props
Prop
Type
Default
Description
actionToastAction | undefinedNot setOne verb as a small ghost button { label, onClick, undo? }; undo shows the undo key and Mod+Z runs it while the toast is up
busyToastBusy | undefinedNot setWork in progress { done?, total?, onStop? }: a spinner, an 'N of M' count with a progress line, and Stop. A busy toast has no timer.
descriptionReact.ReactNodeNot setOne sentence more, if it helps
onDismiss(() => void) | undefinedNot setDraws the dismiss button
Provider.childrenRequiredReact.ReactNodeNot set—
Provider.durationnumber | undefinedNot setDefault milliseconds on screen. Anything under 5000 is raised to 5000; 0 keeps toasts until dismissed.
Provider.positionToastPosition | undefinedbottom-endbottom-centertop-centerNot setWhere the stack sits.
titleReact.ReactNodeNot setOne line on what happened
toneToastTone | undefinedwarningdangerneutralsuccessneutralThe outcome. Semantic tones draw an icon in the tone's ink; the plane, title and body never change colour. Only danger announces urgently.

Accessibility

  • Only the danger tone announces urgently; every other toast is polite
  • Leave enough time to read it: five seconds is the floor
  • Never let colour be the only signal: the icon and the words carry the outcome
  • Toast buttons do not take focus from the page on a press
  • AlertalternativeUse Alert for persistent inline messages
  • DialogalternativeUse Dialog for messages requiring user action

Next steps