UI.MD

Toast

Opinionated layouts for toasts that carry more than one line of text: media, title and description, actions under the copy, and a list of secondary actions behind a disclosure.

Installation

$
npx shadcn@latest add https://ui.mattdowney.com/r/toast.json

Usage

import {
  showToast, Toast, ToastRow, ToastMedia,
  ToastContent, ToastTitle, ToastDescription,
  ToastActions, ToastAction, ToastDisclosure, ToastClose,
  ToastPanel, ToastSection, ToastOption,
} from "@/components/ui/toast"

Examples

Default

Actions sit under the text, not beside it, so they keep their full label. Pick a cell to move where toasts land.

Toast position

position="bottom-right"

Secondary actions behind a disclosure

The one or two actions worth interrupting for stay in the toast; the rest go in ToastPanel, three or four at most. Opening the panel cancels the dismiss timer for good, since a countdown under a list of choices fails WCAG 2.2.1 (Timing Adjustable). Move the toast to a top cell to watch the panel open downward.

Toast position

position="bottom-right"

Grouped actions, wider column

Add label to ToastSection only when the actions sort into distinct jobs, as they do here; most panels are one flat list and want no headings. Omit dismissAfter and the toast waits until it is acted on, and raising width on the Toaster lifts the cap it can grow toward.

Toast position

position="bottom-right"

API Reference

PropTypeDefaultDescription
showToast(render, options)(id) => ReactElement, { dismissAfter?, ...ExternalToast }-Fires the toast. Named showToast rather than toast so it never collides with sonner's own toast(). Wraps toast.custom(), pins sonner's duration to Infinity so the card owns its dismiss timer, and gives sonner's list item the width floor it otherwise lacks.
dismissAfternumber-On showToast options. Milliseconds before the toast auto-dismisses. Pauses on hover, on focus, and while the tab is hidden. Omit to keep the toast up until it is acted on.
position"top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right""bottom-right"On <Toaster />, alongside width. A card grows away from the edge it is anchored to, so a bottom toast opens its panel upward and a top toast opens downward. No change is needed on the card itself.
widthnumber | string400On <Toaster />. A ceiling, not a fixed width: a toast sizes to its own content between a 300px floor and this cap, so a one-line confirmation stays small. Both bounds live on the list, not the card, since sonner positions each toast absolutely inside the column.
expandedboolean-On Toast. Controlled disclosure state. Pair with onExpandedChange; leave both off for uncontrolled. Worth controlling when several toasts can stack at once: sonner measures a toast's height only when its JSX identity changes, so re-firing showToast with the same id on expand is what keeps the toasts behind it correctly offset. Passing it WITHOUT onExpandedChange pins the panel open, which is the decision-card shape described in the notes: drop the ToastDisclosure, add a ToastClose, and expect no dismiss timer. Escape then dismisses the card rather than collapsing it, since there is nothing to collapse back to. A pinned card is also the one case the stacking caveat above does not apply to, because it is born at full height and sonner measures it correctly on the first pass.
labelstring"Notification options"On Toast. Accessible name applied once the panel is open, when the card reads as a group of controls rather than a status line.
labelReactNode-On ToastSection. Optional, and usually left off: most panels are one flat list of three or four actions. Add it only when the actions sort into distinct jobs, in which case it names the group for screen readers as well as sighted users.
variant / sizeButtonProps-On ToastAction and ToastDisclosure. Both render a kit Button and pass these straight through. The action defaults to default, the disclosure to ghost, and both sit at sm, one step below the button default. ToastOption takes neither: it is a menu-item row, not a button.
dismissOnClickbooleantrueOn ToastAction and ToastOption. Dismisses the toast after the handler runs.