Toast
Stacked, swipeable notifications built on Base UI's toast manager. Mount the Toaster once, then fire toasts imperatively from anywhere.
Playground
toast.add({
type: "success",
title: "Changes saved",
description: "Sunday, December 03, 2023 at 9:00 AM",
})Preview
Call toast.add with a title and optional description. New toasts stack behind the frontmost one and expand when you hover or focus the stack.
<Button
variant="outline"
onClick={() =>
toast.add({
title: "Event has been created",
description: "Sunday, December 03, 2023 at 9:00 AM",
})
}
>
Show toast
</Button>
<Toaster />Installation
npx shadcn@latest add https://espresso-base-ui.vercel.app/r/toast.jsonUsage
import {
Toast,
ToastAction,
ToastClose,
ToastContent,
ToastDescription,
ToastPortal,
ToastProvider,
ToastTitle,
ToastViewport,
Toaster,
createToastManager,
toast,
useToastManager,
} from "@/components/ui/toast"// Mount once – e.g. in your root layout
<Toaster />
// Then fire toasts from anywhere, even outside React
toast.add({
type: "success",
title: "Changes saved",
description: "Your profile has been updated.",
})Types
type picks the leading icon: success, info, warning, error, or a spinning loading indicator. Omit it for a plain toast.
toast.add({ type: "success", title: "Changes saved successfully" })
toast.add({ type: "info", title: "New version available" })
toast.add({ type: "warning", title: "Your session will expire soon" })
toast.add({ type: "error", title: "Failed to save changes" })
toast.add({ type: "loading", title: "Processing your request" })With action
actionProps renders a text button inside the toast – pass any button props, typically children and onClick. toast.add returns the toast id so the action can close it.
const id = toast.add({
title: "Event has been created",
description: "Sunday, December 03, 2023 at 9:00 AM",
actionProps: {
children: "Undo",
onClick: () => {
toast.close(id)
toast.add({ title: "Undone" })
},
},
})Promise
toast.promise shows a loading toast, then updates it in place to the success or error state. Each state takes a string, an options object, or a callback receiving the resolved value / error.
const promise = new Promise((resolve) =>
setTimeout(() => resolve({ name: "Toast" }), 1500)
)
toast.promise(promise, {
loading: "Loading...",
success: (data) => data.name + " has been added",
error: "Error",
})Duration & dismiss
timeout overrides the 5 second auto-dismiss per toast – 0 keeps it open until closed. toast.close() without an id dismisses every open toast.
toast.add({
title: "Persistent toast",
description: "This toast won't auto-dismiss",
timeout: 0,
})
toast.close() // dismiss allAPI reference
The module exports a ready-made toast manager (created with createToastManager) and a Toaster that wires the provider, portal, viewport and a styled toast list to it. Call createToastManager yourself for a scoped manager (pass it to Toaster via toastManager), or drop down to the individual parts with useToastManager to build a fully custom renderer.
toast
| Prop | Type | Default | Description |
|---|---|---|---|
| add | (options) => string | – | Creates a toast and returns its id. Passing an existing id updates that toast in place and refreshes its timer. |
| close | (id?: string) => void | – | Closes the toast with the given id – or every open toast when called without one. |
| update | (id, options) => void | – | Patches an open toast with any subset of the add options. |
| promise | (promise, { loading, success, error }) => Promise | – | Tracks a promise through loading, success and error states in a single toast. Each state accepts a string, an options object, or a callback receiving the result / error. |
toast.add options
| Prop | Type | Default | Description |
|---|---|---|---|
| title | ReactNode | – | Heading line of the toast. |
| description | ReactNode | – | Supporting copy below the title. |
| type | "success" | "info" | "warning" | "error" | "loading" | – | Picks the leading icon (tinted per type; loading spins). Omit for no icon. |
| timeout | number | 5000 | Milliseconds before auto-dismiss. 0 keeps the toast open until closed manually. |
| priority | "low" | "high" | "low" | How screen readers announce the toast – politely (low) or urgently (high). |
| actionProps | ButtonHTMLAttributes | – | Props for the inline action button (children, onClick, …). The action renders only when provided. |
| onClose | () => void | – | Called when the toast is closed. |
| onRemove | () => void | – | Called after the toast is removed from the list once its exit animation finishes. |
Toaster
| Prop | Type | Default | Description |
|---|---|---|---|
| toastManager | ToastManager | toast | The manager whose toasts this Toaster renders. Defaults to the exported module-level manager. |
| timeout | number | 5000 | Default auto-dismiss time (ms) for toasts without their own timeout. |
| limit | number | 3 | Maximum toasts displayed at once – the oldest is removed to make room. |
| Component | Description |
|---|---|
| Toaster | All-in-one mount: ToastProvider + ToastPortal + ToastViewport + a styled list of the manager's toasts. |
| ToastProvider | Context provider for manual composition. Takes toastManager, timeout and limit. |
| ToastPortal | Portals the viewport to the document body (data-slot="toast-portal"). |
| ToastViewport | Fixed bottom-right landmark that positions the stack (data-slot="toast-viewport"). |
| Toast | Root surface for one toast (data-slot="toast"). Owns the stacking, swipe and enter/exit transforms. |
| ToastContent | Inner row layout for icon, text and buttons (data-slot="toast-content"). Fades out when behind the frontmost toast. |
| ToastTitle | Renders the toast's title from the manager (data-slot="toast-title"). |
| ToastDescription | Renders the toast's description (data-slot="toast-description"). |
| ToastAction | Blue-tinted text action rendered as a ghost Button (data-slot="toast-action"). Appears only when the toast has actionProps. |
| ToastClose | Icon close button with aria-label="Close toast" and an enlarged hit area (data-slot="toast-close"). |
Accessibility & styling hooks
Toasts are announced by screen readers according to their priority, the close button carries aria-label="Close toast", and every part exposes a data-slot attribute (including the internal toast-icon wrapper) for CSS overrides. The stack is driven by Base UI state attributes – data-expanded while the viewport is hovered or focused, data-starting-style / data-ending-style during enter and exit, data-swipe-direction while swiping to dismiss, and data-limited when a toast exceeds the limit – together with CSS variables like --toast-index and --toast-height, so the collapse, peek and swipe animations can be retuned entirely in CSS.