Skip to main content

Installation

npx shadcn@latest add sonner

Setup

Add the Toaster component to your app:
import { Toaster } from "@/components/ui/sonner"

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head />
      <body>
        <main>{children}</main>
        <Toaster />
      </body>
    </html>
  )
}

Usage

import { toast } from "sonner"
toast("Event has been created.")

Component API

Toaster

Global toast container component.
const Toaster = ({ ...props }: ToasterProps) => {
  const { theme = "system" } = useTheme()

  return (
    <Sonner
      theme={theme as ToasterProps["theme"]}
      className="toaster group"
      icons={{
        success: <CircleCheckIcon />,
        info: <InfoIcon />,
        warning: <TriangleAlertIcon />,
        error: <OctagonXIcon />,
        loading: <Loader2Icon className="animate-spin" />,
      }}
      {...props}
    />
  )
}

toast Function

The toast function is the main API for showing toasts. Basic:
toast("Message")
With Description:
toast("Event created", {
  description: "Your event has been scheduled.",
})
Types:
toast.success("Success message")
toast.error("Error message")
toast.warning("Warning message")
toast.info("Info message")
toast.loading("Loading...")

Examples

Basic Toast

import { toast } from "sonner"

function Example() {
  return (
    <Button onClick={() => toast("Event has been created.")}>
      Show Toast
    </Button>
  )
}

Toast Types

Different toast types:
<div className="flex flex-col gap-2">
  <Button onClick={() => toast.success("Success!")}>
    Success
  </Button>
  <Button onClick={() => toast.error("Error occurred")}>
    Error
  </Button>
  <Button onClick={() => toast.warning("Warning message")}>
    Warning
  </Button>
  <Button onClick={() => toast.info("Info message")}>
    Info
  </Button>
  <Button onClick={() => toast.loading("Loading...")}>
    Loading
  </Button>
</div>

With Description

Toast with additional description:
toast("Event created", {
  description: "Monday, January 3rd at 6:00pm",
})

With Action

Toast with action button:
toast("Event created", {
  action: {
    label: "Undo",
    onClick: () => console.log("Undo"),
  },
})

Promise Toast

Show toast for async operations:
toast.promise(
  fetch("/api/data"),
  {
    loading: "Loading...",
    success: (data) => "Data loaded successfully",
    error: "Error loading data",
  }
)

Custom Duration

toast("Event created", {
  duration: 5000, // 5 seconds
})

Position

Change toast position:
// In your Toaster component
<Toaster position="top-center" />
<Toaster position="top-right" />
<Toaster position="bottom-left" />
<Toaster position="bottom-center" />
<Toaster position="bottom-right" />

Rich Content

Toast with custom JSX:
toast(
  <div className="flex items-center gap-2">
    <CheckCircle2 className="h-4 w-4" />
    <span>Custom content</span>
  </div>
)

Dismissible

Control dismissibility:
toast("Cannot dismiss", {
  dismissible: false,
})

Form Submission

Practical example with form:
function FormExample() {
  const handleSubmit = async (data: FormData) => {
    try {
      toast.loading("Saving changes...")
      await saveData(data)
      toast.success("Changes saved successfully")
    } catch (error) {
      toast.error("Failed to save changes", {
        description: error.message,
      })
    }
  }

  return <form onSubmit={handleSubmit}>...</form>
}

Delete Confirmation

function DeleteButton() {
  const handleDelete = () => {
    toast("Are you sure?", {
      action: {
        label: "Delete",
        onClick: async () => {
          await deleteItem()
          toast.success("Item deleted")
        },
      },
      cancel: {
        label: "Cancel",
        onClick: () => toast.dismiss(),
      },
    })
  }

  return <Button onClick={handleDelete}>Delete</Button>
}

Update Toast

Update an existing toast:
const toastId = toast.loading("Uploading...")

// Later...
toast.success("Upload complete", { id: toastId })

Customization

The component includes custom icons and theming:
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" />,
}}

API Reference

For complete API documentation, see Sonner documentation.

Credits

Sonner is built and maintained by Emil Kowalski.

Build docs developers (and LLMs) love