ask-sonner

Guides setup, usage, styling, and troubleshooting of the Sonner React toast library.

34.1k|1.9k|Updated Mar 16, 2026
One-click install
npx skills add https://github.com/emilkowalski/skills --skill ask-sonner
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: ask-sonner
Source: https://github.com/emilkowalski/skills/tree/main/skills/ask-sonner
Command: npx skills add https://github.com/emilkowalski/skills --skill ask-sonner

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill requires sonner.

What problem does it solve?

Working with the Sonner toast library involves many small decisions and pitfalls: where to mount the Toaster, which toast() call to use, why toasts duplicate, lose styles, or ignore dark mode. This Skill provides authoritative answers and exact API references so you wire up and debug Sonner correctly the first time.

Core Features & Use Cases

  • Setup and call selection: Mount one <Toaster /> at the root and pick the right call — plain, typed, loading, promise, action buttons, or fully headless toast.custom().
  • Styling and theming: Follow an escalation ladder from defaults and richColors through classNames with !important to headless custom JSX, plus icon swapping and dark-mode theming via theme="system" or next-themes.
  • Troubleshooting table: Diagnose common failures such as duplicate toasts from two Toasters, missing styles in Astro or Shadow DOM, toasts hidden behind modals, and stuck toast.promise loading states.
  • Use Case: Your toasts appear twice in a Next.js app — the Skill identifies a second Toaster mounted in a page alongside the layout and tells you to keep exactly one at the root.

Quick Start

Ask how to set up Sonner in a Next.js app and show a success toast after a form submission.

Frequently Asked Questions about ask-sonner

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I set up Sonner toasts in a Next.js app?

Mount a single `<Toaster />` in your root layout.tsx — it works inside server components — then call `toast()` from any client-side event handler or effect. Never render the Toaster per-page or conditionally, since a second mounted Toaster duplicates every toast.

How do I show a loading toast that becomes a success toast in Sonner?

Use `toast.promise(promise, { loading, success, error })` to tie the toast lifecycle to a promise, or manage it manually: store the id from `toast.loading('Uploading…')` and later call `toast.success('Uploaded', { id })` to update the same toast.

Why do my Sonner toasts appear twice?

Duplicate toasts usually mean two Toasters are mounted, such as one in the layout and one in a page — keep exactly one. It can also come from calling `toast()` inside an effect under React StrictMode's dev double-invoke; fire from the event handler or pass a stable id instead.

Why are my Tailwind classes not working on Sonner toasts?

Sonner's injected default styles win the cascade over your classes. Mark classes as `!important` (e.g. `!text-red-900`), or use `unstyled` or the headless `toast.custom()` approach for full control over the toast markup and styling.

Does Sonner support dark mode automatically?

No — the `theme` prop defaults to `'light'` and does not track the OS. Set `theme="system"` on the Toaster, or wire your theme provider by passing the resolved theme from next-themes, e.g. `<Toaster theme={resolvedTheme} />`.

Why is my Sonner toast stuck on loading forever?

A `toast.promise` toast stays in the loading state when its promise never settles — the first argument must be a promise (or a function returning one) that actually resolves or rejects. Also check for `duration: Infinity` or `dismissible: false` on manually managed toasts.