Toast

Sonner underneath, our markup on top: it owns the stack, the timers and the announcements; we own every pixel. Mount ToastRegion once at the app root and call toast() from anywhere. A plain card with the tone carried by its icon: default, success, destructive, warning, info, and loading, which spins and should usually be given no timeout. A thin line shows the time left and pauses on hover; older toasts wait behind, and one that leaves dissolves.

Tones

The cards themselves, standing still. A toast lasts about five seconds, which is long enough to read one and far too short to compare three — so these are rendered rather than fired.

Note savedLinked to Alice Chen.
Added to your brainDana Whitfield is now yours.
Couldn't save your changesThe backend didn't answer.
Sync moved to the backgroundWe'll tell you when it lands.
Hydrating your Second Brain#455 in queue
<Toast title="Note saved" description="Linked to Alice Chen." />
<Toast title="Added to your brain" tone="success" />
<Toast title="Couldn't save" tone="destructive" />
<Toast title="Sync moved to the background" tone="info" />
<Toast title="Hydrating your Second Brain" tone="loading" />

Playground

Render <ToastRegion /> once at the app root; queue from anywhere. The tone is a leading icon on a plain card. A thin line counts down the time left and pauses while you hover the stack. Older toasts wait behind, and a toast that leaves dissolves; under reduced motion it fades.

tone
toast({"title":"Dana Whitfield is in your brain","description":"With her last 6 emails.","tone":"success","action":{"label":"Undo","href":"#"}}, { timeout: 6000 });

<ToastRegion />