Actions
Toast
A short status message that appears, announces itself, and leaves on its own.
When to use it: Use it to confirm background results such as saves; keep anything needing a decision in a dialog.
Example
import { Button } from "@comp0/react";
import { Toast, ToastDismiss, ToastProvider, ToastRegion, useToast } from "@comp0/react";
import { XMarkIcon } from "@heroicons/react/16/solid";
function Triggers() {
const { notify } = useToast();
return (
<div className="flex flex-wrap gap-2">
<Button
className="rounded bg-teal-600 px-3 py-2.5 text-base text-white sm:py-2 sm:text-sm"
onClick={() => notify("Saved")}
>
Save
</Button>
<Button
className="rounded border border-red-950/10 px-3 py-2.5 text-base text-red-700 sm:py-2 sm:text-sm dark:border-red-200/10 dark:text-red-300"
onClick={() =>
notify("Connection lost. Changes stopped syncing.", { kind: "alert", timeout: null })
}
>
Go offline
</Button>
</div>
);
}
export function Example() {
return (
<ToastProvider>
<Triggers />
<ToastRegion className="inset-auto right-4 bottom-4 m-0 flex w-72 flex-col gap-2 border-0 bg-transparent p-0">
{(toast) => (
<Toast
toast={toast}
className="flex items-start justify-between gap-3 rounded border border-zinc-950/10 bg-white p-3 text-base text-zinc-900 shadow-lg sm:text-sm data-[kind=alert]:border-red-600/30 data-[kind=alert]:text-red-700 dark:border-white/10 dark:bg-zinc-900 dark:text-zinc-50 dark:data-[kind=alert]:border-red-400/30 dark:data-[kind=alert]:text-red-300"
>
<span>{toast.content}</span>
<ToastDismiss className="rounded p-0.5 text-zinc-500 hover:bg-zinc-950/10 hover:text-zinc-800 dark:text-zinc-400 dark:hover:bg-white/10 dark:hover:text-zinc-100">
<XMarkIcon className="size-4" aria-hidden="true" />
</ToastDismiss>
</Toast>
)}
</ToastRegion>
</ToastProvider>
);
}Anatomy
Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.
A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.
ToastProvider
Owns the notification queue; it owns no DOM. Does not add a DOM element.
useToast
Hook returning notify and dismiss; throws outside ToastProvider. Does not add a DOM element.
ToastRegion
Labelled live region shown in the top layer only while toasts exist; hover or focus pauses auto-dismiss timers. Owns a DOM element.
Toast
One notification; role=status for polite kinds and role=alert for urgent ones. Owns a DOM element.
ToastDismissOptional
Native button pre-wired to dismiss its surrounding toast. Owns a DOM element.
Step by step
- 1
Add the main part
Wrap the app in ToastProvider and call notify from useToast where results happen.
- 2
Add the supporting parts
Add one ToastRegion whose render prop returns a Toast with a ToastDismiss inside.
- 3
Make the behavior clear
Use kind "alert" plus timeout null for urgent messages people must not miss.
Exampletsx <ToastRegion>{(toast) => <Toast toast={toast}>{toast.content}<ToastDismiss /></Toast>}</ToastRegion>
Keyboard
- ⇥
- Reaches the dismiss button and other controls inside each toast.
- Esc
- Intentionally not a global shortcut; dismissal stays on the buttons inside the region.
Forms and accessibility
Toasts do not create native form values.
Accessibility checklist
- Keep messages short and self-contained; role=status announces politely and role=alert interrupts, so reserve alert for urgent problems.
- Auto-dismiss timers pause while the region is hovered or contains focus, and sticky toasts (timeout null) stay for anything people must act on.
- The toast renders its live-region role and content in the same commit, which browsers announce for items appended one at a time; keep updates as new toasts instead of mutating an existing one.
API reference
import { Button, Toast, ToastDismiss, ToastProvider, ToastRegion, useToast } from "@comp0/react";ToastProvider
Context onlyOwns the notification queue; it owns no DOM.
| Prop | Type | Description |
|---|---|---|
children | ReactNode | App content plus one ToastRegion; call useToast anywhere inside. |
useToast
Context onlyHook returning notify and dismiss; throws outside ToastProvider.
| Prop | Type | Description |
|---|---|---|
notify(content, options?) | (content: ReactNode, options?: { kind?: "status" | "alert"; timeout?: number | null }) => string | Queues a toast and returns its id; kind defaults to status, timeout to 6000 ms, and null keeps it until dismissed. |
dismiss(id) | (id: string) => void | Removes a queued toast by id. |
ToastRegion
DOM elementLabelled live region shown in the top layer only while toasts exist; hover or focus pauses auto-dismiss timers.
| Prop | Type | Description |
|---|---|---|
children | (toast: ToastRecord) => ReactNode | Render prop that returns one Toast per queued record. |
aria-label | string | Region name for assistive technology; defaults to "Notifications". |
forceMount | boolean | Keep the region rendered while the queue is empty. |
Toast
DOM elementOne notification; role=status for polite kinds and role=alert for urgent ones.
| Prop | Type | Description |
|---|---|---|
toast | ToastRecord | The queued record this item renders. |
children | ReactNode | Custom layout; defaults to the record's content. |
ToastDismiss
OptionalDOM elementNative button pre-wired to dismiss its surrounding toast.
| Prop | Type | Description |
|---|---|---|
aria-label | string | Accessible name; defaults to "Dismiss notification". |
Style hooks
Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.
[data-kind=alert]on Toast
- The toast is urgent.
[data-kind=status]on Toast
- The toast is polite.
:popover-openon ToastRegion
- The region is shown in the top layer.