Live preview
"use client";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function SonnerDemo() {
return (
<Button
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>
);
}
#Installation
npx shadcn@latest add https://neobrutal-ui.andongmin.com/r/sonner.json"use client";
import { useTheme } from "next-themes";
import { Toaster as Sonner, type ToasterProps } from "sonner";
import {
CircleCheckIcon,
InfoIcon,
TriangleAlertIcon,
OctagonXIcon,
Loader2Icon,
} from "lucide-react";
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme();
return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
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={
{
fontFamily: "inherit",
overflowWrap: "anywhere",
} as React.CSSProperties
}
toastOptions={{
unstyled: true,
classNames: {
toast:
"bg-background text-foreground border-border border-2 font-heading shadow-shadow rounded-base text-[13px] flex items-center gap-2.5 p-4 w-[356px] [&:has(button)]:justify-between",
description: "font-base",
actionButton:
"font-base border-2 text-[12px] h-6 px-2 bg-main text-main-foreground border-border rounded-base shrink-0",
cancelButton:
"font-base border-2 text-[12px] h-6 px-2 bg-secondary-background text-foreground border-border rounded-base shrink-0",
error: "bg-black text-white",
loading:
"[&[data-sonner-toast]_[data-icon]]:flex [&[data-sonner-toast]_[data-icon]]:size-4 [&[data-sonner-toast]_[data-icon]]:relative [&[data-sonner-toast]_[data-icon]]:justify-start [&[data-sonner-toast]_[data-icon]]:items-center [&[data-sonner-toast]_[data-icon]]:flex-shrink-0",
},
}}
{...props}
/>
);
};
export { Toaster };
#Usage
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Toaster } from "@/components/ui/sonner";Mount the <Toaster /> once near the root of your app.
<Toaster />You can then trigger toasts from any client component.
<Button
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>#Examples
#Success
"use client";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function SonnerSuccessDemo() {
return <Button onClick={() => toast.success("Event has been created")}>Success</Button>;
}
#Info
"use client";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function SonnerInfoDemo() {
return (
<Button onClick={() => toast.info("Be at the area 10 minutes before the event time")}>
Info
</Button>
);
}
#Warning
"use client";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function SonnerWarningDemo() {
return (
<Button onClick={() => toast.warning("Event start time cannot be earlier than 8am")}>
Warning
</Button>
);
}
#Error
"use client";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function SonnerErrorDemo() {
return <Button onClick={() => toast.error("Event has not been created")}>Error</Button>;
}
#Action
"use client";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function SonnerActionDemo() {
return (
<Button
onClick={() =>
toast("Event has been created", {
action: {
label: "Undo",
onClick: () => console.log("Undo"),
},
})
}
>
Action
</Button>
);
}
#Cancel
"use client";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function SonnerCancelDemo() {
return (
<Button
onClick={() =>
toast("Event has been created", {
cancel: {
label: "Cancel",
onClick: () => console.log("Cancel"),
},
})
}
>
Cancel
</Button>
);
}
#Promise
"use client";
import { toast } from "sonner";
import { useState } from "react";
import { Button } from "@/components/ui/button";
export default function SonnerPromiseDemo() {
const [loading, setLoading] = useState(false);
const promise = () =>
new Promise((resolve) => setTimeout(() => resolve({ name: "Sonner" }), 2000));
return (
<Button
disabled={loading}
aria-busy={loading}
onClick={() => {
setLoading(true);
const request = promise();
toast.promise(request, {
loading: "Loading...",
success: () => {
return `Sonner toast has been added`;
},
error: "Error",
});
request.finally(() => setLoading(false));
}}
>
{loading ? "Loading..." : "Promise"}
</Button>
);
}