Sonner
An opinionated toast component for React. Perfect for notifications, confirmations, and user feedback in Next.js, TypeScript, and Tailwind CSS applications.
You know those little notifications that pop up to tell you something worked? Or when you need to undo an action? Sonner makes toast notifications feel polished and thoughtful instead of jarring interruptions that users immediately dismiss.
Basic notification
Clean, simple toast messages:
Just import and call toast()
anywhere in your app. This free open source React component handles positioning, animations, and accessibility so your notifications feel professional.
npx shadcn@latest add sonner
Why Sonner beats basic alerts
Toast notifications done right actually improve user experience:
- Non-blocking - Users can keep working while notifications show
- Contextual timing - Messages appear exactly when they're relevant
- Undo actions - Let users reverse mistakes immediately
- Status updates - Show loading, success, and error states naturally
- Swipe to dismiss - Intuitive mobile-friendly interactions
- Smart positioning - Never covers important interface elements
Toast types for every situation
Different message types
Success, error, loading, and default styles:
Promise handling
Automatic loading states for async operations:
Custom notifications
Icons, persistence, and completely custom JSX:
These patterns cover real scenarios - form submissions, file uploads, API calls, user actions. Each toast type gives users the right visual cue for what's happening.
Perfect for user feedback
Sonner shines when you need to confirm actions, show progress, or let users undo things. Works great with forms, data operations, settings changes, bulk actions. Much better than modal dialogs that force users to stop what they're doing.
Built by Emil Kowalski. Full TypeScript support. Styled with Tailwind CSS to match the shadcn design system.
Setup
Add the Toaster
component to your root layout:
import { Toaster } from "@repo/shadcn-ui/components/ui/sonner"
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<main>{children}</main>
<Toaster />
</body>
</html>
)
}
API Reference
toast()
The main function for creating toast notifications.
Function | Description |
---|---|
toast(message, options?) | Basic toast with message and optional config |
toast.success(message, options?) | Success toast with checkmark icon |
toast.error(message, options?) | Error toast with error icon |
toast.loading(message, options?) | Loading toast with spinner |
toast.promise(promise, options) | Handles promise states automatically |
toast.custom(jsx, options?) | Completely custom toast content |
toast.dismiss(id?) | Dismiss specific toast or all toasts |
Toast Options
Configuration object for customizing individual toasts:
Option | Type | Default | Description |
---|---|---|---|
description | string | ReactNode | - | Additional text below the main message |
duration | number | 4000 | Time in milliseconds before auto-dismissal |
action | object | - | Primary button with label and onClick handler |
cancel | object | - | Secondary button with label and onClick handler |
icon | ReactNode | - | Custom icon to display |
closeButton | boolean | false | Show close button |
dismissible | boolean | true | Allow user dismissal |
id | string | - | Custom ID for programmatic control |
position | string | - | Override default position for this toast |
onDismiss | (toast) => void | - | Callback when toast is dismissed |
onAutoClose | (toast) => void | - | Callback when toast auto-closes |
className | string | - | Additional CSS classes |
style | object | - | Inline styles |
unstyled | boolean | false | Remove default styling |
Promise Options
Special configuration for promise-based toasts:
Option | Type | Description |
---|---|---|
loading | string | ReactNode | Message during promise execution |
success | string | function | Message or function returning message on success |
error | string | function | Message or function returning message on error |
toast.promise(uploadFile(), {
loading: "Uploading...",
success: (data) => `${data.filename} uploaded successfully`,
error: "Upload failed",
})
Toaster Component
Container component that renders all toasts:
Prop | Type | Default | Description |
---|---|---|---|
position | string | bottom-right | Where toasts appear on screen |
expand | boolean | false | Expand toasts by default |
visibleToasts | number | 3 | Maximum number of visible toasts |
closeButton | boolean | false | Add close button to all toasts |
richColors | boolean | false | Enhanced colors for success/error states |
theme | 'light' | 'dark' | 'system' | light | Color theme |
offset | string | 32px | Distance from screen edges |
dir | 'ltr' | 'rtl' | 'auto' | ltr | Text direction |
hotkey | string[] | ['⌥', 'T'] | Keyboard shortcut to focus toasts |
toastOptions | object | {} | Default options for all toasts |
Available Positions
Position | Description |
---|---|
top-left | Upper left corner |
top-center | Top center of screen |
top-right | Upper right corner |
bottom-left | Lower left corner |
bottom-center | Bottom center of screen |
bottom-right | Lower right corner (default) |
Common patterns
Form submission feedback
const handleSubmit = async (data) => {
const promise = submitForm(data)
toast.promise(promise, {
loading: "Saving changes...",
success: "Settings updated successfully",
error: "Failed to save changes",
})
}
Undo actions
const deleteItem = (id) => {
// Perform deletion
removeItem(id)
toast("Item deleted", {
action: {
label: "Undo",
onClick: () => restoreItem(id),
},
})
}
Persistent notifications
const showImportantMessage = () => {
const id = toast("System maintenance in 5 minutes", {
duration: Infinity,
action: {
label: "Dismiss",
onClick: () => toast.dismiss(id),
},
})
}
Design tips for better toasts
Keep these principles in mind when using toast notifications:
- Be specific - "File uploaded" is better than "Success"
- Show progress - Use loading states for operations that take time
- Enable undo - Let users reverse destructive actions immediately
- Don't overuse - Too many toasts become noise users ignore
- Time appropriately - Important messages can stay longer
- Position thoughtfully - Don't cover critical interface elements
- Test on mobile - Make sure swipe gestures work naturally
- Consider accessibility - Screen readers should announce toast content
Slider
An input where the user selects a value from within a given range. Perfect for settings, filters, and controls in React applications with Next.js, TypeScript, and Tailwind CSS.
Switch
A control that allows users to toggle between checked and not checked states. Perfect for settings, preferences, and feature toggles in React applications with Next.js, TypeScript, and Tailwind CSS.