Toast

Toast

Stacked, swipeable notifications built on Base UI's toast manager. Mount the Toaster once, then fire toasts imperatively from anywhere.

Playground

title
type
description
action
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.json

Usage

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 all

API 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

PropTypeDefaultDescription
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

PropTypeDefaultDescription
titleReactNode–Heading line of the toast.
descriptionReactNode–Supporting copy below the title.
type"success" | "info" | "warning" | "error" | "loading"–Picks the leading icon (tinted per type; loading spins). Omit for no icon.
timeoutnumber5000Milliseconds 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).
actionPropsButtonHTMLAttributes–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

PropTypeDefaultDescription
toastManagerToastManagertoastThe manager whose toasts this Toaster renders. Defaults to the exported module-level manager.
timeoutnumber5000Default auto-dismiss time (ms) for toasts without their own timeout.
limitnumber3Maximum toasts displayed at once – the oldest is removed to make room.
ComponentDescription
ToasterAll-in-one mount: ToastProvider + ToastPortal + ToastViewport + a styled list of the manager's toasts.
ToastProviderContext provider for manual composition. Takes toastManager, timeout and limit.
ToastPortalPortals the viewport to the document body (data-slot="toast-portal").
ToastViewportFixed bottom-right landmark that positions the stack (data-slot="toast-viewport").
ToastRoot surface for one toast (data-slot="toast"). Owns the stacking, swipe and enter/exit transforms.
ToastContentInner row layout for icon, text and buttons (data-slot="toast-content"). Fades out when behind the frontmost toast.
ToastTitleRenders the toast's title from the manager (data-slot="toast-title").
ToastDescriptionRenders the toast's description (data-slot="toast-description").
ToastActionBlue-tinted text action rendered as a ghost Button (data-slot="toast-action"). Appears only when the toast has actionProps.
ToastCloseIcon 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.

Search documentation

Search the component docs