An opinionated toast component for React providing comprehensive toast notifications with customization options
—
The main React component that renders and manages all toast notifications. The Toaster component should be included once in your application, typically at the root level, and will handle the display of all toast messages created throughout your app.
The primary React component for rendering toast notifications with comprehensive configuration options.
/**
* React component that renders the toast notification container
* @param props - Configuration options for the toaster
* @param ref - Optional ref to the underlying HTML element
*/
const Toaster: React.ForwardRefExoticComponent<ToasterProps & React.RefAttributes<HTMLElement>>;
interface ToasterProps {
/** Invert colors for dark backgrounds */
invert?: boolean;
/** Theme mode: light, dark, or system-based */
theme?: "light" | "dark" | "system";
/** Position of toast notifications on screen */
position?: "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top-center" | "bottom-center";
/** Keyboard shortcut to expand toasts (default: ['altKey', 'KeyT']) */
hotkey?: string[];
/** Enable rich colors for enhanced visual styling */
richColors?: boolean;
/** Keep toasts expanded by default */
expand?: boolean;
/** Default duration for toasts in milliseconds */
duration?: number;
/** Gap between toast notifications in pixels */
gap?: number;
/** Maximum number of visible toasts at once */
visibleToasts?: number;
/** Show close button on all toasts */
closeButton?: boolean;
/** Default options applied to all toasts */
toastOptions?: ToastOptions;
/** Custom CSS class for the toaster container */
className?: string;
/** Custom styles for the toaster container */
style?: React.CSSProperties;
/** Offset from viewport edges */
offset?: Offset;
/** Mobile-specific offset from viewport edges */
mobileOffset?: Offset;
/** Text direction for RTL languages */
dir?: "rtl" | "ltr" | "auto";
/** Custom icons for different toast types */
icons?: ToastIcons;
/** ARIA label for the notification container */
containerAriaLabel?: string;
/** Pause toasts when browser tab is not visible */
pauseWhenPageIsHidden?: boolean;
}
interface ToastOptions {
/** Default CSS class for toast elements */
className?: string;
/** Show close button on toasts */
closeButton?: boolean;
/** Default CSS class for description text */
descriptionClassName?: string;
/** Default styles for toast container */
style?: React.CSSProperties;
/** Default styles for cancel buttons */
cancelButtonStyle?: React.CSSProperties;
/** Default styles for action buttons */
actionButtonStyle?: React.CSSProperties;
/** Default duration for all toasts */
duration?: number;
/** Disable default styling for all toasts */
unstyled?: boolean;
/** Default CSS classes for toast elements */
classNames?: ToastClassnames;
}
type Offset = {
top?: string | number;
right?: string | number;
bottom?: string | number;
left?: string | number;
} | string | number;
interface ToastIcons {
/** Icon for success toasts */
success?: React.ReactNode;
/** Icon for info toasts */
info?: React.ReactNode;
/** Icon for warning toasts */
warning?: React.ReactNode;
/** Icon for error toasts */
error?: React.ReactNode;
/** Icon for loading toasts */
loading?: React.ReactNode;
/** Icon for close button */
close?: React.ReactNode;
}import React from "react";
import { Toaster, toast } from "sonner";
function App() {
return (
<div>
{/* Add Toaster once in your app */}
<Toaster />
<main>
{/* Your app content */}
<button onClick={() => toast("Hello!")}>
Show Toast
</button>
</main>
</div>
);
}import { Toaster } from "sonner";
// Top-right positioning
<Toaster position="top-right" />
// Bottom-center positioning
<Toaster position="bottom-center" />
// Top-left with custom offset
<Toaster
position="top-left"
offset={{ top: 20, left: 20 }}
/>import { Toaster } from "sonner";
// Dark theme
<Toaster theme="dark" />
// System theme (follows OS preference)
<Toaster theme="system" />
// Rich colors enabled
<Toaster richColors />
// Inverted colors for dark backgrounds
<Toaster invert />import { Toaster } from "sonner";
<Toaster
position="top-center"
toastOptions={{
duration: 5000,
style: {
background: "#363636",
color: "#fff",
},
className: "my-toast",
actionButtonStyle: {
background: "#007bff",
color: "white",
},
cancelButtonStyle: {
background: "#dc3545",
color: "white",
},
}}
closeButton
richColors
expand
visibleToasts={5}
gap={12}
/>import { Toaster } from "sonner";
import { CheckIcon, XIcon, InfoIcon } from "your-icon-library";
<Toaster
icons={{
success: <CheckIcon />,
error: <XIcon />,
info: <InfoIcon />,
close: <XIcon size={12} />,
}}
/>import { Toaster } from "sonner";
// Right-to-left text direction
<Toaster dir="rtl" />
// Auto-detect from document
<Toaster dir="auto" />import { Toaster } from "sonner";
<Toaster
containerAriaLabel="Notifications"
hotkey={["altKey", "KeyT"]} // Alt + T to expand toasts
pauseWhenPageIsHidden={true} // Pause when tab not visible
/>import { Toaster } from "sonner";
<Toaster
position="bottom-center"
// Different offsets for mobile vs desktop
offset="16px"
mobileOffset="8px"
// Fewer visible toasts on mobile
visibleToasts={3}
// Smaller gap on mobile
gap={8}
/>type Position =
| "top-left"
| "top-right"
| "bottom-left"
| "bottom-right"
| "top-center"
| "bottom-center";type Theme = "light" | "dark" | "system";// String or number for all sides
offset="20px"
offset={20}
// Object for individual sides
offset={{
top: "20px",
right: "16px",
bottom: "20px",
left: "16px"
}}All options in ToastOptions are applied as defaults to every toast:
toastOptions={{
// Default duration for all toasts
duration: 5000,
// Default styling
style: { background: "#333" },
className: "my-default-toast",
// Default button styles
actionButtonStyle: { background: "blue" },
cancelButtonStyle: { background: "red" },
// Show close button on all toasts
closeButton: true,
// Default classNames for elements
classNames: {
toast: "custom-toast",
title: "custom-title",
description: "custom-description"
}
}}// Default hotkey (Alt + T)
<Toaster hotkey={["altKey", "KeyT"]} />
// Custom hotkey (Ctrl + Shift + N)
<Toaster hotkey={["ctrlKey", "shiftKey", "KeyN"]} />
// Multiple keys
<Toaster hotkey={["metaKey", "KeyK"]} /> // Cmd/Win + K<Toaster
// Limit visible toasts for performance
visibleToasts={3}
// Pause when page is hidden to save resources
pauseWhenPageIsHidden={true}
// Smaller gap reduces layout recalculations
gap={8}
/>// CSS Modules
<Toaster className={styles.toaster} />
// Tailwind CSS
<Toaster
className="font-sans"
toastOptions={{
className: "bg-white shadow-lg rounded-lg",
actionButtonStyle: { background: "#3b82f6" }
}}
/>
// Styled Components
const StyledToaster = styled(Toaster)`
/* Custom styles */
`;// _app.tsx (Next.js) or App.tsx (Create React App)
import { Toaster } from "sonner";
export default function App() {
return (
<>
<YourAppContent />
<Toaster
position="top-right"
theme="system"
richColors
closeButton
pauseWhenPageIsHidden
/>
</>
);
}import { useTheme } from "your-theme-context";
import { Toaster } from "sonner";
function ThemedToaster() {
const { theme } = useTheme();
return <Toaster theme={theme} />;
}import { Toaster } from "sonner";
function App() {
const showToaster = process.env.NODE_ENV === "development" || isProduction;
return (
<div>
<YourApp />
{showToaster && <Toaster />}
</div>
);
}Install with Tessl CLI
npx tessl i tessl/npm-sonner