Toast
A global toast notification component with a store-based imperative API
Installation
Usage
Basic Usage
Call Toaster.success / Toaster.error / Toaster.warning / Toaster.info / Toaster.loading imperatively. Mount a single <Toaster /> once in your app to render the toast list; it is fixed at the top-center of the viewport and shows up to 3 stacked toasts by default.
"use client";
import { Button, Toaster } from "@/ui";
export default function Demo() {
return (
<div className="flex flex-col items-center gap-4">
<Toaster />
<div className="flex flex-wrap justify-center gap-2">
<Button
onClick={() =>
Toaster.success({
title: "Changes saved",
description: "Your profile has been updated.",
})
}
>
Success
</Button>
<Button
onClick={() =>
Toaster.error({
title: "Upload failed",
description: "The file exceeds the 10 MB limit.",
})
}
>
Error
</Button>
<Button
onClick={() =>
Toaster.warning({
title: "Storage almost full",
description: "9.2 GB of 10 GB used.",
})
}
>
Warning
</Button>
<Button
onClick={() =>
Toaster.info({
title: "New version available",
description: "Reload to update to v2.4.0.",
})
}
>
Info
</Button>
<Button
onClick={() => {
const id = Toaster.loading({ title: "Loading data..." });
setTimeout(() => Toaster.dismiss(id), 3000);
}}
>
Loading
</Button>
<Button
onClick={() =>
Toaster.info({
title: "New version available",
description: "Reload to update to v2.4.0.",
closable: true,
})
}
>
Closable
</Button>
</div>
</div>
);
}
Closing toasts
Toasts are notifications only — they never carry action buttons. When an interaction is required (confirm, retry, open details), use the Dialog instead.
Two ways to close a toast:
- Pass
closableto render a close button in the toast's top-right corner. Toaster.loading(and every other method) returns a toast id: pass it toToaster.dismiss(id)to close exactly that toast when the work finishes. CallingToaster.dismiss()without an id dismisses every toast.
Promise
Toaster.promise shows a loading toast and automatically replaces it with a success or error toast when the promise settles.
"use client";
import { Button, Toaster } from "@/ui";
function deploy(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Deployed to production");
}, 2000);
});
}
export default function Demo() {
return (
<div className="flex flex-col items-center gap-4">
<Toaster />
<Button
onClick={() =>
Toaster.promise(deploy, {
loading: "Deploying...",
success: (message) => message,
error: () => "Deployment failed, please retry.",
})
}
>
Start Deploy
</Button>
</div>
);
}
API Reference
High-level Components
Toaster
The toast host. Render it once in your application; it subscribes to the global toast store and renders the toast list fixed at the top-center of the viewport. It also carries the imperative methods below.
If multiple <Toaster /> instances are mounted, only the first one acts as the host and renders toasts; the rest render nothing, so accidental duplicate mounts can never cause duplicated toasts or inconsistent hover pausing.
Collapsed toasts stack with a slight vertical offset; hovering expands them into a vertical list and pauses auto-dismiss.
| Prop | Type | Default | Description |
|---|---|---|---|
visibleToasts | number | 3 | Maximum number of toasts rendered at the same time |
className | ClassNameValue | - | Custom class name for the container |
...props | React.ComponentProps<"div"> | - | Remaining props are passed through to the container section element |
Imperative methods:
| Method | Type | Description |
|---|---|---|
success | (options: ToastItemProps) => number | Shows a success toast, returns the toast id |
error | (options: ToastItemProps) => number | Shows an error toast, returns the toast id |
warning | (options: ToastItemProps) => number | Shows a warning toast, returns the toast id |
info | (options: ToastItemProps) => number | Shows an info toast, returns the toast id |
loading | (options: ToastItemProps) => number | Shows a persistent loading toast (never auto-dismisses) |
dismiss | (id?: string | number) => void | Dismisses a toast by id; without an id, dismisses all toasts |
promise | <T>(promise: () => Promise<T>, data: PromiseData<T>) => void | Loading toast that upgrades to success/error on settle |
ToastItemProps
Options accepted by every imperative method.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | number | - | Toast id; auto-assigned by the store when the toast is created |
title | React.ReactNode | - | Toast title |
description | React.ReactNode | - | Secondary text below the title |
type | "success" | "error" | "warning" | "info" | "loading" | - | Icon type; set automatically by the semantic methods |
icon | React.ReactNode | type icon | Custom icon, overrides the built-in type icon |
duration | number | 5000 | Auto-dismiss delay in ms; Infinity disables auto-dismiss (loading toasts always persist) |
closable | boolean | false | Renders a close button in the toast's top-right corner |
onClose | (event: CloseEvent) => void | - | Fired with type: "auto" | "manual" on dismiss start and type: "complete" after removal |
classNames | { root?, icon?, content?, title?, description?, close? } | - | Custom classes for each part of the toast card |
styles | { root?, icon?, content?, title?, description?, close? } | - | Inline styles for each part of the toast card |
CloseEvent
| Field | Type | Description |
|---|---|---|
type | "auto" | "manual" | "complete" | Why the toast closed; "complete" fires after removal |
id | string | number (optional) | The toast id |
PromiseData<T>
| Field | Type | Description |
|---|---|---|
loading | React.ReactNode | Title shown while the promise is pending |
success | React.ReactNode | ((data: T) => React.ReactNode) | Title on resolve |
error | React.ReactNode | ((error: unknown) => React.ReactNode) | Title on reject |
Composable Components
The toast card is built from the parts below. They are exported so you can assemble a custom toast card when the composite API is not enough.
ToastRoot
The toast card container. Carries the card surface (border, shadow, background) and the stack/exit animation states driven by data-expanded / data-exiting.
| Prop | Type | Default | Description |
|---|---|---|---|
className | ClassNameValue | - | Custom CSS class |
Supports all native <div> attributes.
ToastIcon
Wrapper for the leading icon.
| Prop | Type | Default | Description |
|---|---|---|---|
className | ClassNameValue | - | Custom CSS class |
Supports all native <div> attributes.
ToastContent
Wrapper for the title and description column.
| Prop | Type | Default | Description |
|---|---|---|---|
className | ClassNameValue | - | Custom CSS class |
Supports all native <div> attributes.
ToastTitle
The title text.
| Prop | Type | Default | Description |
|---|---|---|---|
className | ClassNameValue | - | Custom CSS class |
Supports all native <div> attributes.
ToastDescription
The secondary text below the title.
| Prop | Type | Default | Description |
|---|---|---|---|
className | ClassNameValue | - | Custom CSS class |
Supports all native <div> attributes.
ToastClose
The top-right close button, rendered by the composite when closable is set.
| Prop | Type | Default | Description |
|---|---|---|---|
className | ClassNameValue | - | Custom CSS class |
Supports all native <button> attributes.