Overlays
Toaster
Toast notifications on sonner, following the next-themes theme.
Preview
Install
pnpm dlx shadcn@latest add @abnormal/sonnerUsage
"use client";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Toaster } from "@/components/ui/sonner";
export default function SonnerDemo() {
return (
<div className="flex flex-wrap justify-center gap-2">
<Toaster />
<Button variant="outline" onClick={() => toast("Draft saved")}>
Default
</Button>
<Button variant="outline" onClick={() => toast.success("Message sent")}>
Success
</Button>
<Button variant="outline" onClick={() => toast.error("Could not send")}>
Error
</Button>
</div>
);
}
Source
"use client";
import { useTheme } from "next-themes";
import { Toaster as Sonner, type ToasterProps } from "sonner";
import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react";
/** Toasts sit on a popover surface; success and failure speak only through the icon color, without tinting the whole block. */
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme();
return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
icons={{
success: <CircleCheckIcon className="size-4 text-success" />,
info: <InfoIcon className="size-4" />,
warning: <TriangleAlertIcon className="size-4" />,
error: <OctagonXIcon className="size-4 text-destructive" />,
loading: <Loader2Icon className="size-4 animate-spin" />,
}}
style={
{
"--normal-bg": "var(--popover-bg)",
"--normal-text": "var(--text)",
"--normal-border": "var(--border)",
"--border-radius": "var(--radius-panel)",
} as React.CSSProperties
}
toastOptions={{
classNames: {
toast: "cn-toast",
},
}}
{...props}
/>
);
};
export { Toaster };