Skip to content
Drivn
4 min read

React Toast Component Examples

Copy-paste React Toast examples: success and error toasts, a toast with a description, an action button with Undo, and positioning the Toaster.

A toast is a transient, floating notification that confirms a completed action without interrupting the user — "Saved", "Sent", "File deleted" — and then dismisses itself on a timer. The Toast component in Drivn is a thin Toaster wrapper around Sonner, the headless toast library, with five lucide-react icons pre-wired for the success, info, warning, error, and loading states. You install it with npx drivn add toast, mount the Toaster once near your app root, then call toast() from anywhere.

Every example below is TypeScript, because Drivn ships TypeScript-only .tsx source installed by the Drivn CLI under @/components/ui/toast. The toast function is re-exported straight from Sonner, so toast.success, toast.error, toast.info, and toast.warning each fire the matching typed toast with its pre-wired icon, and the surface is themed from Drivn's --card and --border tokens so it matches a Card out of the box.

The examples cover a basic success and error toast, the full set of typed variants, a toast with a description line, a toast with an Undo action button, and how to position the Toaster in any corner of the viewport.

A basic success and error toast

The simplest use is two buttons that fire a typed toast. Mount the Toaster once — it renders the Sonner toast region — then call toast.success or toast.error from any click handler. Each typed call shows its pre-wired lucide icon: a CheckCircle2 for success and an XCircle for error, both sized w-4 h-4 against the message.

The wrapper is a client component because the buttons attach onClick handlers, and the Toaster only needs to be mounted once in your tree — placing it in your root layout means every page can call toast() without mounting its own. The toast auto-dismisses on Sonner's default timer, and stacks with any other active toasts. This is the canonical pattern for confirming a completed action.

1"use client"
2
3import { Toaster, toast } from "@/components/ui/toast"
4
5export default function Example() {
6 return (
7 <div>
8 <button onClick={() => toast.success("Saved successfully")}>
9 Success
10 </button>
11 <button onClick={() => toast.error("Something went wrong")}>
12 Error
13 </button>
14 <Toaster />
15 </div>
16 )
17}

The full set of typed variants

Beyond success and error, the toast function exposes info and warning, each with its own pre-wired icon — Info and AlertTriangle respectively — plus a plain toast() call for a neutral message with no icon. Every variant accepts the same options object, so you can attach a description second line to any of them, as the success and error examples below show.

This covers the common notification taxonomy: a neutral default for "Changes saved", success for a confirmed write, error for a failed operation, info for a non-urgent heads-up, and warning for something the user should notice but that is not a failure. Each maps to the icon Drivn wired in its Toaster, so the visual language stays consistent across your whole app without any per-call icon wiring.

1<Button variant="secondary" size="sm" onClick={() => toast("Changes saved")}>
2 Default
3</Button>
4<Button variant="secondary" size="sm" onClick={() => toast.success("Published!", { description: "Your post is now live." })}>
5 Success
6</Button>
7<Button variant="secondary" size="sm" onClick={() => toast.error("Something went wrong", { description: "Please try again." })}>
8 Error
9</Button>
10<Button variant="secondary" size="sm" onClick={() => toast.info("New update available")}>
11 Info
12</Button>
13<Button variant="secondary" size="sm" onClick={() => toast.warning("Low storage space")}>
14 Warning
15</Button>

A toast with an action button

For toasts the user can act on — the classic "deleted, but Undo" pattern — pass an action object as the second argument with a label and an onClick. Sonner renders the label as an inline button inside the toast; clicking it runs your handler and dismisses the toast. Drivn inherits this API unchanged because it re-exports toast directly from Sonner.

This is the right pattern for any reversible destructive action: delete the item optimistically, show the toast with an Undo action, and only commit the deletion if the toast dismisses without the action being clicked. It keeps the main flow fast — no confirm dialog — while still giving the user a safety net. Pair it with a Button elsewhere in the flow for the primary trigger.

1// Toast with action button
2toast.success("File deleted", {
3 action: {
4 label: "Undo",
5 onClick: () => restoreFile(),
6 },
7})

Positioning the Toaster

The toast region's corner is controlled by the position prop on the Toaster, not on individual toast() calls — set it once where you mount the component. Sonner supports all six anchors: top-left, top-center, top-right, bottom-left, bottom-center, and bottom-right. The default is bottom-right, which keeps notifications out of the way of primary content and navigation.

Because positioning lives on the Toaster, every toast in your app shares the same corner — you configure it in your root layout, alongside your Drivn install, and forget about it. If you need a different position for a specific surface, mount a second Toaster with its own position, though for most apps a single bottom-right or bottom-center region is the cleanest choice. The configuration API below shows each anchor.

1<Toaster position="top-left" />
2<Toaster position="top-center" />
3<Toaster position="top-right" />
4<Toaster position="bottom-left" />
5<Toaster position="bottom-center" />
6<Toaster position="bottom-right" />
Get started

Install Drivn in one command

Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.

npx drivn@latest create

Requires Node 18+. Works with npm, pnpm, and yarn.

Enjoying Drivn?
Star the repo on GitHub to follow new component releases.
Star →

Frequently asked questions

Install the component with npx drivn add toast, mount the Toaster once near your app root, then call toast() from any event handler. For typed toasts use toast.success, toast.error, toast.info, or toast.warning, each of which fires the matching message with its pre-wired lucide icon. The toast function is re-exported from Sonner, so the full Sonner API is available.

Mount the Toaster once, high in your tree — typically in your root layout — so every page can call toast() without rendering its own region. The Toaster renders the Sonner toast container that all toast() calls feed into. Mounting it more than once creates duplicate regions, so a single instance in the layout is the standard setup for a Next.js app.

Pass a description string in the options object as the second argument, for example toast.success("Published!", { description: "Your post is now live." }). The description renders as a secondary line beneath the main message. Every toast variant — default, success, error, info, and warning — accepts the same options object, so descriptions work identically across all of them.

Pass an action object as the second argument with a label and an onClick handler, such as toast.success("File deleted", { action: { label: "Undo", onClick: () => restoreFile() } }). Sonner renders the label as an inline button; clicking it runs your handler and dismisses the toast. This is the standard pattern for reversible destructive actions like delete-with-undo.

Set the position prop on the Toaster component, not on individual toast() calls. Sonner supports six anchors: top-left, top-center, top-right, bottom-left, bottom-center, and bottom-right, with bottom-right as the default. Because position lives on the Toaster, every toast in your app shares that corner, so you configure it once in your root layout.