Transient, screen-level notification that confirms an action or surfaces a short-lived message.
Description
Toast is a compound component that renders a compact, self-contained surface (a <div> with role="status") composed of an icon, a title, a description, and optional action, close, or progress affordances. Unlike InlineAlert, it is meant to float over the page in a screen-level viewport (top-right, bottom-center, and so on) and to disappear once the user has read it.
Reach for it when the message is short-lived and the user does not need to act on it to keep working: "Draft saved", "Copied to clipboard", "Connection restored". Seven semantic variants cover the full status spectrum, ToastAction gives you a single follow-up affordance ("Undo", "Retry"), and ToastProgress shows the remaining lifetime for auto-dismissing queues.
The component ships in two layers. Toast and its slots are presentational — render them anywhere you want that surface. On top of that sits a screen-level queue: mount Toaster once and call toast() from anywhere. There is deliberately no provider — the queue is a single module-level store, so exactly one stack exists on screen and the newest entry is always the one in front.
The viewport shows the newest three entries at a time, so a burst of notifications never floods the screen. They collapse into a deck and expand into a full list on hover or keyboard focus, the countdown pauses while the deck is expanded so nothing is lost mid-read, and entries pushed together file in one after another rather than appearing all at once.
The stack runs on a single countdown rather than a timer per card. It is measured from the newest arrival, so a burst of toasts resets it to the full 6s, and when it elapses the whole stack goes at once — including anything still waiting behind the three visible slots. Draining card by card instead would leave the user watching wave after wave of the same notification group.
Don't use Toast for status that belongs to a specific section; use InlineAlert. If you need to interrupt the user with a confirm or cancel decision, use Dialog. For per-field validation messages, use the helper-text slot on Field so the message stays scoped to the input.
Installation
Anatomy
The queue — one viewport, mounted once:
The card — what the viewport renders for you, and what you compose by hand:
Usage
Mount Toaster once — typically in the root layout. Mounting it more than once renders every toast in each viewport, so the component warns in development if it sees a second one.
Then push notifications from anywhere — no provider and no hook required, so this works in event handlers, effects, and plain functions alike.
toast() returns the new entry's id. useToast() is available when you need to read the live queue or dismiss entries: it returns { toasts, toast, dismiss, dismissAll }. Entries share a single 6s countdown measured from the newest arrival, and the whole stack clears when it elapses; pass duration to give an entry its own timer or duration: null to keep it until dismissed. Toaster takes position for the anchored corner and visibleToasts (default 3) for how many render at once.
To render the surface without the queue — inline in a page, or inside your own viewport — compose Toast directly.
Examples
Variants
variant selects the semantic intent. The seven options map to the system's status token sets: primary for brand, neutral for system rows, info / success / warning / danger for status, and away for idle states.
Appearances
appearance tunes the surface treatment without changing the semantic variant. solid is the default high-emphasis filled treatment; soft is a tinted block; outline keeps the border colored and the fill transparent; default is the quiet, card-like surface.
With Action
Use ToastAction to add a single follow-up affordance, typically "Undo", "Retry", or "View". The action button is wired through the design system's Button so its variant tracks the toast's appearance automatically.
With Progress
ToastProgress renders a thin progress bar at the bottom edge that tracks how close an auto-dismissing toast is to closing. Inside the queue, pass progress: true and the viewport drives the bar off the same timer that dismisses the entry — including pausing it while the stack is expanded. Composing Toast by hand, set duration to the toast's lifetime and flip value on the next frame, paired with a setTimeout that dismisses it.
Without Icon
The icon slot is optional. Omit ToastIcon for short, text-only notifications where the wording carries enough context on its own.
Dismissible
Queue entries get the trailing close button automatically; pass dismissible: false to suppress it. Pass duration: null to opt an entry out of auto-dismiss entirely so it waits for the user, as below. Either way the card runs an internal fade-and-scale transition and the root's onDismiss fires once it ends — that's the moment the entry leaves the queue.
Accessibility
Toast is a custom composition, not a Radix primitive. The root renders with role="status", so assistive tech announces the contents as a polite live region; the announcement is queued behind the user's current task rather than interrupting them.
ARIA notes:
- The root sets
role="status"; for time-critical alerts that should preempt the current announcement, override withrole="alert"via the standard DOM prop. - The leading icon is decorative; provide a meaningful
ToastTitleso screen readers have something to announce. ToastProgressis purely visual and is markedaria-hidden: the auto-dismiss countdown carries no information the user must act on, and the rootrole="status"already announces the toast — so it is intentionally not exposed as aprogressbar.- The close button inherits its accessible name from
CloseButton("Close"). data-dismissedflips while the exit transition is playing; useful for CSS, not announced by AT.
Styling
Tailwind override: pass className to merge Tailwind classes with the component's CVA classes (via cn()):
Data slots and attributes: the component sets these for CSS targeting:
data-slot="toast"on the root element.data-slot="toast-body"on the icon + content wrapper.data-slot="toast-icon"on the icon wrapper.data-slot="toast-content"on the text column.data-slot="toast-title"on the title text.data-slot="toast-description"on the description text.data-slot="toast-action"on the action button.data-slot="toast-close"on the dismiss button.data-slot="toast-progress"on the progress track,data-slot="toast-progress-indicator"on the moving bar.data-variant="<variant>",data-appearance="<appearance>"on the root.data-dismissedon the root while the exit transition is running.
Target a specific state in CSS:
Related Components
- InlineAlert: in-flow status surface anchored to a section; use when the message belongs to a specific region.
- Dialog: blocking, focus-trapping interrupt; use when the user must respond before continuing.
- Field: per-field validation surface with helper or error text scoped to a single input.
- Banner: page-level announcement that spans the full chrome; use for site-wide notices.
API Reference
Toast
The root surface. Renders a <div> with role="status", owns the dismiss state, and broadcasts variant / appearance to every sub-component via context. Extends React.ComponentProps<"div">, so any standard div attribute (id, aria-*, onClick, etc.) is accepted.
Props
Variants
ToastBody
Layout wrapper that groups the icon and the text column so trailing affordances (action, close, progress) stay aligned. Extends React.ComponentProps<"div">.
Props
ToastIcon
Leading icon slot. Extends React.ComponentProps<"span">. Sizes its child SVG to size-5 and colors it from the active variant / appearance context.
Props
ToastContent
Wraps the title and description into a single column. Extends React.ComponentProps<"div">.
Props
ToastTitle
The bold one-line summary. Renders a <p>. Extends React.ComponentProps<"p">.
Props
ToastDescription
The supporting body text. Renders a <p> and tones its color down on soft / default appearances. Extends React.ComponentProps<"p">.
Props
ToastAction
A single trailing action button. Wraps the design system Button; its variant / appearance are picked automatically from the toast's appearance. Extends React.ComponentProps<typeof Button>.
Props
ToastClose
Trailing close button. Wraps CloseButton, picks the right variant for the current appearance, and calls the root's internal dismiss handler before invoking your onClick. Extends React.ComponentProps<typeof CloseButton>.
Props
ToastProgress
Thin progress bar at the bottom edge of the toast, used to convey the remaining lifetime of an auto-dismissing toast. Extends React.ComponentProps<"div">.