# How to Migrate from Deprecated shadcn/ui Toast Components to Sonner

> Easily migrate from deprecated shadcnui toast components to Sonner. Learn the simple steps to update your imports and integrate Sonner for a seamless transition in your project.

- Repository: [shadcn-ui/ui](https://github.com/shadcn-ui/ui)
- Tags: migration-guide
- Published: 2026-02-26

---

**To migrate from the deprecated `toast` and `toaster` components to Sonner, install the `sonner` package, replace your `Toaster` import with the wrapper from `@/registry/new-york/ui/sonner`, and update all `toast` function imports from the local registry path to `import { toast } from "sonner"`.**

The **shadcn/ui** library has officially deprecated the legacy Radix-based toast system in favor of **Sonner**, a modern toast library with built-in theme support and a richer API. This migration guide provides the exact code changes required, referencing the source files from the shadcn/ui repository where the deprecation is declared and the new implementation resides.

## Understanding the Deprecation

The deprecation is explicitly defined in [`packages/shadcn/src/registry/constants.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/registry/constants.ts), where the `DEPRECATED_COMPONENTS` array marks both `toast` and `toaster` as replaced by `sonner`【61†L61-L73】. While the old components remain available in the `deprecated/www/registry/new-york/ui/` directory for backwards compatibility, the new implementation lives in [`deprecated/www/registry/new-york/ui/sonner.tsx`](https://github.com/shadcn-ui/ui/blob/main/deprecated/www/registry/new-york/ui/sonner.tsx)【61†L1-L9】.

**Sonner** offers significant improvements over the legacy system: automatic integration with `next-themes` for light/dark mode switching, built-in helper methods like `toast.success()` and `toast.promise()`, and a lighter runtime footprint compared to the Radix-based implementation.

## Step 1: Install the Sonner Dependency

Ensure the `sonner` package is installed in your project. The shadcn/ui monorepo currently locks this dependency at version 2.0.7 in [`pnpm-lock.yaml`](https://github.com/shadcn-ui/ui/blob/main/pnpm-lock.yaml)【61†L7075】.

```bash
npm i sonner

```

Leave your existing `next-themes` installation as-is; the Sonner wrapper depends on it for automatic theme detection.

## Step 2: Replace the Toaster Component

Update your root layout or main application file to import the `Toaster` from the new Sonner wrapper instead of the deprecated toaster component.

**Before (deprecated):**

```tsx
import { Toaster } from "@/registry/new-york/ui/toaster";

export function App() {
  return (
    <>
      <Toaster />
      {/* ...rest of app */}
    </>
  );
}

```

**After (Sonner):**

```tsx
import { Toaster } from "@/registry/new-york/ui/sonner";

export function App() {
  return (
    <>
      <Toaster />
      {/* ...rest of app */}
    </>
  );
}

```

The new `Toaster` component in [`sonner.tsx`](https://github.com/shadcn-ui/ui/blob/main/sonner.tsx) forwards all props to the underlying Sonner library while injecting the current theme via `useTheme()` from `next-themes`【61†L1-L9】.

## Step 3: Migrate the Toast Function

Replace all imports of the `toast` function from the local registry path with the direct import from the `sonner` package. This is the most critical change for functionality.

**Before (deprecated):**

```tsx
import { toast } from "@/registry/new-york/ui/toast";

function handleSave() {
  toast("Saved successfully!", {
    description: "Your changes have been persisted.",
    action: {
      label: "Undo",
      onClick: () => console.log("undo"),
    },
  });
}

```

**After (Sonner):**

```tsx
import { toast } from "sonner";

function handleSave() {
  toast("Saved successfully!", {
    description: "Your changes have been persisted.",
    action: {
      label: "Undo",
      onClick: () => console.log("undo"),
    },
  });
}

```

## Step 4: Utilize Sonner's Enhanced API

Sonner provides built-in helper methods that eliminate the need for manual variant management. These methods are not available in the deprecated shadcn implementation.

**Success and error variants:**

```tsx
import { toast } from "sonner";

// Automatic success styling
toast.success("Item added.", {
  description: "Your new item is now in the list.",
});

// Automatic error styling
toast.error("Failed to add item", {
  description: "Please try again later.",
});

```

**Promise-based toasts:**

```tsx
// Automatic loading, success, and error states
toast.promise(
  fetch("/api/save"),
  {
    loading: "Saving…",
    success: "Saved!",
    error: "Failed to save.",
  }
);

```

## Step 5: Remove Legacy UI Components

Delete all imports and usage of the legacy toast primitives from your codebase. Remove references to `ToastProvider`, `ToastViewport`, `Toast`, `ToastTitle`, `ToastDescription`, `ToastAction`, and `ToastClose` from the old [`toast.tsx`](https://github.com/shadcn-ui/ui/blob/main/toast.tsx) file. Sonner handles the viewport, positioning, and action buttons internally, significantly simplifying your component tree.

If you previously customized toast icons, pass them via the `icons` prop to the new `Toaster` component:

```tsx
import { Toaster } from "@/registry/new-york/ui/sonner";
import { Check, X, Info } from "lucide-react";

export function App() {
  return (
    <Toaster
      icons={{
        success: <Check className="size-4" />,
        error: <X className="size-4" />,
        info: <Info className="size-4" />,
      }}
    />
  );
}

```

## Step 6: Verify Theme Compatibility

Ensure your application root is wrapped with the `next-themes` provider. The Sonner wrapper in [`deprecated/www/registry/new-york/ui/sonner.tsx`](https://github.com/shadcn-ui/ui/blob/main/deprecated/www/registry/new-york/ui/sonner.tsx) calls `useTheme()` to synchronize the toast appearance with your application's current theme【61†L1-L9】. Without this provider, toasts will not respond to theme changes.

## Summary

- **The deprecation** is declared in [`packages/shadcn/src/registry/constants.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/registry/constants.ts), which maps `toast` and `toaster` to `sonner` replacements.
- **Installation** requires the `sonner` package (v2.0.7) as your only new runtime dependency.
- **Component migration** involves changing the `Toaster` import from `@/registry/.../ui/toaster` to `@/registry/.../ui/sonner`.
- **Function migration** requires updating `import { toast } from "..."` to `import { toast } from "sonner"`.
- **API enhancements** include `toast.success()`, `toast.error()`, and `toast.promise()` for streamlined UX patterns.
- **Cleanup** involves removing all legacy `ToastProvider`, `ToastViewport`, and related primitive components.

## Frequently Asked Questions

### Is the old toast component removed completely?

No, the legacy components remain in the `deprecated/www/registry/new-york/ui/` directory, specifically in [`toast.tsx`](https://github.com/shadcn-ui/ui/blob/main/toast.tsx)【61†L1-L9】, for backwards compatibility. However, they are marked for removal in future releases and receive no new features or bug fixes. Migrating to Sonner ensures you stay on the supported path.

### Do I need to install next-themes separately?

If you already use `next-themes` in your project, no additional installation is required. The Sonner wrapper imports `useTheme` from `next-themes` to handle automatic light/dark mode switching. If you are not using `next-themes`, the wrapper will still function but will default to the light theme unless you manually configure the `theme` prop on the `Toaster` component.

### How do I customize Sonner toast icons and styling?

Pass custom icons via the `icons` prop on the `Toaster` component, or override default classes using the `toastOptions.classNames` prop. The wrapper already provides default styling with `className="toaster group"`, but you can extend this via the `className` prop on `Toaster` or by targeting Sonner's CSS classes in your global stylesheet.

### Will my existing toast trigger logic break during migration?

Basic toast calls using the pattern `toast("Message", { description: "...", action: {...} })` remain functionally identical. The only breaking change is the import path. However, if you relied on the old `Toast` component's `variant` prop for styling, you must replace those calls with `toast.success()`, `toast.error()`, or `toast.info()` to achieve the same visual results.