How to Add Toast Notifications to React
Step-by-step guide to add toast notifications to any React app with the Drivn CLI — mount one Toaster, fire typed toasts, and add descriptions and actions.
Adding toast notifications to a React app used to mean picking a library, learning its queue API, and styling a container to match your design. Drivn collapses that into one command and a component you own. The Toast in Drivn is a thin Toaster wrapper around Sonner, the headless toast engine by Emil Kowalski, with five lucide-react icons pre-wired — success, error, info, warning, and a spinning loader — and the surface themed from Drivn's own --card and --border design tokens. You get Sonner's proven stacking, swipe-to-dismiss, and auto-dismiss timing, with defaults that already match the rest of your UI.
Because the Toaster manages a portal and a queue, its source opens with a 'use client' directive, so it runs on the client — true in any React setup, whether you scaffolded with Vite, Create React App, or Next.js. The pattern is always the same: mount one Toaster near your app root, then call toast() from anywhere. This guide adds the Toast to any React app: install the CLI, mount the container and fire your first toast, use the typed variants with descriptions and an action button, and reposition the container. For the App Router specifics see the Next.js Toast guide; for the shadcn/ui comparison see Drivn vs shadcn/ui Toast.
Prerequisites
Before installing the Toast, confirm your React project has the two things Drivn assumes: Tailwind CSS v4 processing your styles and a @/ path alias pointing at your source directory — the component ships as a .tsx file, so TypeScript is part of the stack. If you scaffolded with create-next-app, npm create vite, or npx drivn@latest create, both are already wired; the installation page lists the minimal config for a custom setup. The Toast wrapper pulls in two runtime packages that the CLI notes for you: sonner, which supplies the toast engine, and lucide-react, which supplies the five variant icons. And because the Toaster renders a portal and owns the toast queue, its source carries a 'use client' directive — mount it inside a client boundary, not directly in a framework's server-rendered tree.
Step 1 — Install Drivn via the CLI
Run the CLI from your project root to add the Toast source. The command writes a single toast.tsx under your UI directory and notes its two peer dependencies, sonner and lucide-react; install them once if they are not already present and you are set. There is no runtime Drivn package to version-lock — the CLI docs cover the flags for targeting a custom path or adding several components in one run. After install the file is yours: a future Drivn release will not overwrite your edits, and the whole wrapper — the icon map keyed by variant and the token-based style object — is a few lines you can read top to bottom. Commit it for a clean baseline before wiring it in.
1 # add the Toast component and note its Sonner + lucide deps 2 npx drivn add toast
Step 2 — Mount the Toaster and fire your first toast
The Toast has two parts: the Toaster container, which you mount once, and the toast() function, which you call to show a message. Mount the Toaster high in your tree — the root component in a Vite or CRA app, or the root layout in Next.js — so a single container serves every screen and you never render a second one. Then import toast in any client component and call it from an event handler: toast.success('Saved') shows a green check, toast.error('Something went wrong') a red cross, each with its pre-wired lucide icon. The container draws nothing until a toast fires, so where you place it affects only stacking order, not layout. The toast auto-dismisses on Sonner's default timer and stacks with any others. See the Toast examples for the full set of patterns.
1 'use client' 2 3 import { Toaster, toast } from '@/components/ui/toast' 4 5 export default function App() { 6 return ( 7 <div> 8 <button onClick={() => toast.success('Saved successfully')}> 9 Save 10 </button> 11 <button onClick={() => toast.error('Something went wrong')}> 12 Fail 13 </button> 14 <Toaster /> 15 </div> 16 ) 17 }
Step 3 — Use typed variants, descriptions, and actions
Beyond success and error, toast exposes info and warning, each with its own pre-wired icon — Info and AlertTriangle — plus a plain toast() call for a neutral message with no icon. Every variant takes the same options object as a second argument: a description string adds a secondary line under the title, and an action object with a label and onClick renders an inline button — the classic "deleted, but Undo" pattern. Drivn inherits this API unchanged because it re-exports toast straight from Sonner, so anything the Sonner docs describe works here. toast.loading returns an id you can pass to a later toast.success(msg, { id }) to swap the spinner for a result in place — the spinning Loader2 Drivn wires is exactly what shows during that phase. Reach for a Button as the trigger and a description line for context.
1 // Typed toasts with a description and an action button 2 toast.warning("Low storage space") 3 4 toast.success("File deleted", { 5 action: { 6 label: "Undo", 7 onClick: () => restoreFile(), 8 }, 9 })
Step 4 — Position and customize the container
Everything the container renders is set in one place — the Toaster you own. Move the toasts by passing a position prop such as top-center or bottom-left; the default is Sonner's bottom-right. The rest is already wired in the source: five lucide-react icons keyed by variant, and a style object that maps Sonner's CSS variables onto Drivn's design tokens — --normal-bg to var(--card), the text to var(--card-foreground), the border to var(--border), and a --border-radius of 12px. Because those read your Tailwind theme tokens, the toast surface re-themes for dark and light mode automatically; adjust the colors in theming and every toast follows. To swap an icon or the radius, edit the object in place — there is no config file and no variant map to thread through. The snippet below shows the position prop; the style block lives verbatim in toast.tsx.
1 <Toaster position="top-center" />
Install Drivn in one command
Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.
Frequently asked questions
Install the Drivn CLI and run npx drivn add toast, which writes toast.tsx into your components directory and notes its sonner and lucide-react peers. Mount the Toaster once near your app root, then import { toast } from "@/components/ui/toast" and call toast.success or toast.error from any client event handler. The component that calls toast must run on the client.
Mount it exactly once, high in your tree so it sits above every screen — the root component in a Vite or Create React App project, or the root layout in Next.js. A single Toaster serves the whole app; never render a second one on a page. Because it draws nothing until a toast fires, its position affects only stacking order, not your layout flow.
Drivn's Toaster pre-wires five lucide-react icons — success, error, info, warning, and a spinning Loader2 — and themes the surface with your --card, --card-foreground, and --border design tokens at a 12px radius. The toast() function is re-exported from Sonner unchanged, so the API is identical while the defaults match the rest of your Drivn UI out of the box, with no extra wiring.
Yes. The Toast is plain React plus Sonner, so it works in any React app — Vite, Create React App, Remix, or Next.js. The only requirement is that the Toaster and the components calling toast() run on the client, which is the default everywhere except a framework with server components. Install with the CLI and the source drops into your project the same way.
Pass an action object as the second argument to any toast call, with a label and an onClick handler: 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. Drivn inherits this API unchanged because it re-exports toast from Sonner.

