Sonner
Shadcn ui: Sonner
Default
Saved
Saved locallyimport { toast } from "sonner" import { Toaster as Sonner } from "sonner" import { useEffect, useState } from "react" import { CircleCheckIcon, InfoIcon, Loader2Icon, OctagonXIcon, TriangleAlertIcon, } from "lucide-react" import { Button } from "@/components/ui/button" // Simple Toaster wrapper that works in Sandpack without next-themes function SandpackToaster() { const [theme, setTheme] = useState<"light" | "dark">("light") useEffect(() => { const checkTheme = () => { const isDark = document.documentElement.classList.contains("dark") setTheme(isDark ? "dark" : "light") } checkTheme() const observer = new MutationObserver(checkTheme) observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"], }) return () => observer.disconnect() }, []) return ( <Sonner position="top-left" theme={theme} icons={{ success: <CircleCheckIcon className="size-4" />, info: <InfoIcon className="size-4" />, warning: <TriangleAlertIcon className="size-4" />, error: <OctagonXIcon className="size-4" />, loading: <Loader2Icon className="size-4 animate-spin" />, }} style={ { "--normal-bg": "var(--popover)", "--normal-text": "var(--popover-foreground)", "--normal-border": "var(--border)", "--border-radius": "var(--radius)", } as React.CSSProperties } /> ) } export function SonnerDemo() { return ( <> <SandpackToaster /> <Button variant="outline" onClick={() => toast("Event has been created", { description: "Sunday, December 03, 2023 at 9:00 AM", action: { label: "Undo", onClick: () => console.log("Undo"), }, }) } > Show Toast </Button> </> ) } export default function App() { return <SonnerDemo />; }