Skip to content

Toast

Stable

A brief, non-blocking notification that confirms an action or reports a background event, then gets out of the way.

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/toast.json

Wrap your app in Toaster once, near the root. It provides the manager, renders the viewport in a portal and stacks toasts in the bottom-right corner (bottom-center on small screens).

app/layout.tsx
import { Toaster } from "@/components/ui/toast"

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Toaster>{children}</Toaster>
      </body>
    </html>
  )
}

Usage

import { toast } from "@/components/ui/toast"
toast.add({
  title: "Changes saved",
  description: "Your profile is up to date.",
  type: "success",
})

toast is a global manager, so you can call it from event handlers, server-action callbacks or plain modules — no hook required. Inside components you can also read the queue with useToastManager().

Examples

Types

type picks the icon and its color: success, info, warning, error and loading. A toast without a type shows no icon — right for neutral confirmations like Invitation sent.

With an action

Give a toast at most one action, and make it a quick recovery like Undo or View. The action must also be possible elsewhere: a toast can vanish before anyone reaches it.

const id = toast.add({
  title: "Conversation archived",
  timeout: 8000,
  actionProps: {
    children: "Undo",
    onClick: () => {
      toast.close(id)
      restoreConversation()
    },
  },
})

Promise

toast.promise shows a loading toast while a promise is pending, then turns the same toast into a success or error message. success and error can be functions that receive the result or the error.

toast.promise(publishPost(), {
  loading: "Publishing post…",
  success: (post) => ({ title: "Post published", description: post.url }),
  error: (error) => ({ title: "Couldn't publish post", description: error.message }),
})

Updating in place

toast.add returns an id. Pass it to toast.update to change the title, description, type or timeout of a toast that is already on screen — one toast that evolves reads better than a stack of three.

Persistent

timeout: 0 keeps a toast until it is dismissed. Use it sparingly, for background conditions that stay true — like being offline — and pair it with priority: "high" so it is announced immediately.

Stacking

Up to three toasts are visible at once (limit on Toaster). Newer toasts push older ones back into a compact stack; hovering or focusing the stack expands it so every toast can be read and acted on. Toasts can be swiped away down or to the right on touch devices.

Guidelines

When to use

  • To confirm that something the person just did has succeeded: saved, sent, copied, archived.
  • To report the outcome of a background task that finished while they were elsewhere.
  • To offer a short window for recovery, like Undo.

When not to use

  • For errors that need a decision or input — use an Alert Dialog or keep the person in context with an inline error.
  • For information that must stay visible — use an Alert.
  • For validation messages. They belong next to the field that failed.

Choosing feedback

ComponentScopeBlocks the task?Persists?Use it for
FieldErrorOne fieldNoUntil fixedInvalid or missing input.
AlertA page or sectionNoUntil the condition changesLimits, outages, summaries of form errors.
ToastThe appNoA few secondsConfirmations and background results.
Alert DialogThe appYesUntil answeredDestructive or irreversible decisions.

Duration

The default timeout is 5 seconds. Increase it for toasts with an action (8 seconds) or more than one line of text — reading speed, not urgency, sets the duration. Toasts pause while hovered or focused, so nobody loses a message they are reading.

Writing

  • Name the object and the outcome: Conversation archived, 3 files uploaded. Skip "successfully" — the check mark says it.
  • Past tense for results, present progressive for work in progress: Publishing post…Post published.
  • Keep it to one line when you can. Use the description only for a detail people need: where it went, what failed, what to try.
  • Don't toast what people can already see. If the list updates in place, the list is the confirmation.
Invoice INV-2041 sent
Delivered to billing@acme.com
Do.Short, specific, and the icon carries the tone.
Success!
Your action was completed successfully.
Don’t.Vague and redundant — it says nothing a check mark couldn't.

Accessibility

  • Announced, not focused. Toasts render in a live region. priority: "low" (the default) is announced politely after the current speech; priority: "high" interrupts. Use high priority only for errors and conditions that need immediate attention.
  • Reachable from the keyboard. The viewport is a landmark region; press F6 to move focus into it. Focusing or hovering pauses every timer.
  • Nothing essential lives only in a toast. Actions like Undo must also be available elsewhere, because people using magnification or switch devices may never reach the toast before it disappears.
  • Motion. Toasts slide in and stack with transforms; under prefers-reduced-motion they appear and disappear without movement.
KeyBehavior
F6
Moves focus to the most recent toast in the viewport.
TabShiftTab
Moves between toasts and their actions.
Esc
Dismisses the focused toast.
EnterSpace
Activates the focused action or close button.

API reference

toast

The global toast manager, created with Base UI's createToastManager().

PropTypeDefault
add(options)

Shows a toast and returns its id. Passing an existing id updates that toast and restarts its timer.

(options: ToastOptions) => stringNo default
update(id, options)

Changes a visible toast in place.

(id: string, options: Partial<ToastOptions>) => voidNo default
close(id?)

Dismisses one toast, or all toasts when called without an id.

(id?: string) => voidNo default
promise(promise, options)

Tracks a promise with one toast that moves from loading to success or error.

(promise: Promise<T>, { loading, success, error }) => Promise<T>No default

Toast options

PropTypeDefault
title

The message. One short line.

ReactNodeNo default
description

Optional detail shown under the title.

ReactNodeNo default
type

Chooses the leading icon. Omit for neutral toasts.

"success" | "info" | "warning" | "error" | "loading" | stringNo default
timeout

Milliseconds before auto-dismiss. 0 keeps the toast until closed.

number5000
priority

How urgently assistive technology announces the toast.

"low" | "high""low"
actionProps

Renders an action button; children is its label.

ComponentProps<'button'>No default
id

Custom id. Adding a toast with an existing id updates it.

stringNo default
onClose

Called when the toast starts closing.

() => voidNo default
onRemove

Called after the exit animation, when the toast leaves the DOM.

() => voidNo default
data

Custom data available to a custom toast renderer.

objectNo default

Toaster

Provides the manager and renders the viewport. Accepts every prop of Base UI's Toast.Provider.

PropTypeDefault
timeout

Default timeout for toasts that don't set one.

number5000
limit

Maximum toasts visible at once. Older toasts are hidden until space frees up.

number3
toastManager

The manager to listen to. Create more with createToastManager().

ToastManagertoast

Parts

Toast, ToastContent, ToastTitle, ToastDescription, ToastAction, ToastClose, ToastViewport and ToastPortal are exported for custom layouts. They wrap the matching Base UI parts with prfct styles; see the Base UI reference for their props.