ComponentsFeedback

Toast

A short notice about something that just happened: a save, a failed upload, a sent invite. Toasts stack in the bottom corner, close on their own, and never take focus away from what someone is doing.

Each closes after 5 seconds

No notifications open

Usage

Toast usageTSX
import { Toaster, toast } from "@tulipfarm/sprout/toast";

// Once, near the root of the app.
<Toaster>
  <App />
</Toaster>

// Anywhere, inside or outside React.
toast.add({
  title: "Invite sent",
  description: "Ana Ruiz can now join the Meadow workspace.",
  type: "success",
});

Toaster mounts a provider and a ready-made viewport. Call toast.add from event handlers, data hooks, or plain modules; it returns an id you can pass to toast.update or toast.close.

Types

type picks the icon: "success" (check), "error" (a cross in the danger color), "warning" (triangle), "info" (circle), and "loading" (spinner). Leave it out for a plain toast with no icon. Toasts close after 5 seconds unless you pass another timeout; timeout: 0 keeps one open until it’s dismissed.

Actions

Pass actionProps to add one small outline button. Its children are the label and its onClick runs before the toast closes. Keep the action optional: the same result must be reachable elsewhere, because the toast can close before someone reaches it.

With action

An Undo button in the toast. Choosing it shows a title-only follow-up.

Isolated managers

createToastManager() makes a separate stack. Hand it to <Toaster toastManager={manager}> and call useToastManager().add from components inside it. Create it once, for example with useState(createToastManager).

Isolated managerTSX
function Controls() {
  const manager = useToastManager();
  return (
    <Button onClick={() => manager.add({ title: "Success example", type: "success", timeout: 5000 })}>
      success
    </Button>
  );
}

export function Example() {
  const [manager] = useState(createToastManager);
  return (
    <Toaster toastManager={manager}>
      <Controls />
    </Toaster>
  );
}

Isolated manager

A Toaster with its own manager. Buttons inside it call useToastManager().add.

Loading and results

toast.promise shows a "loading" toast while the promise runs, then replaces it in place with the success or error options. Each option can be a function of the result or the error.

Loading, then a result

toast.promise shows a loading toast and swaps it for success or error when the work settles.

Custom layout

For a different layout, compose the parts yourself: ToastProvider, ToastPortal (optional), ToastViewport, and a list of Toast roots read from useToastManager().toasts, each holding ToastContent, ToastTitle, ToastDescription, ToastAction, and ToastClose. Title and description fill themselves from the toast; the action renders only when it has a label.

Custom layout

Toast parts composed by hand in a framed viewport: a file icon, Retry only on failures, and swipe right or down to dismiss. These stay until closed.

Upload queue is empty

API

Toaster takes every ToastProvider prop: toastManager (defaults to the shared toast), timeout (5000), and limit (3 visible). toast.add takes title, description, type, timeout, priority, actionProps, onClose, and data.

ToastAction renders a small outline Button and ToastClose a small ghost icon button labeled “Close toast”; pass render to swap either. Toast takes swipeDirection(down and right by default). Every part sets a data-slot, and toastTypeNames lists the types with icons.

Accessibility

The viewport is a polite live region named “Notifications”, so new toasts are announced without moving focus. Press F6 to jump to the stack; Tab then moves through each toast’s action and close button, and focus returns where it was when the stack empties. Hovering or focusing the stack expands it and pauses every timer. Swipe a toast away on touch screens. Pass priority: "high" for an urgent error that should be announced right away.

Toasts slide up over 180ms and the stack reflows over 120–180ms. With reduced motion they only fade. In forced-colors mode each toast keeps a visible border.

Theme tokens

Toasts use --sprout-surface, --sprout-line, --sprout-text, --sprout-muted, --sprout-danger for the error icon,--sprout-shadow-overlay, and the panel radius. They need no brand color, so they look the same with the neutral and TulipFarm themes in light and dark mode.