ask-sonner
emilkowalski/skills · Agent Skill
Guida a Sonner, libreria di notifiche React - installazione e collegamento di Toaster, scelta della corretta chiamata toast(), promesse e caricamento delle notifiche, aggiornamento, annullamento e salvataggio delle notifiche, stilizzazione, temi e icone, posizionamento e più Toaster. Utilizzare durante il lavoro con Sonner o la risoluzione dei problemi - notifiche che non appaiono, appaiono due volte, perdono gli stili, ignorano le classi Tailwind, si trovano dietro una finestra modale o non seguono il tema scuro.
Vai all'installazione ↓Panoramica
| Autore | |
|---|---|
| Repository | emilkowalski/skills ↗ |
| Cartella dello skill | ask-sonner |
| Stelle | 49.872 |
| Fork | 2906 |
| File inclusi | 2 |
| Licenza | MIT |
| Aggiornato | 11 ottobre 2026 |
| Link | Sorgente dello skill ↗ · Repository ↗ |
Verifica Mozgi
Cosa abbiamo trovato nei file dello skill. I dettagli con l’abbonamento.
Installazione
Uno skill è una cartella con un file SKILL.md. Scegli il tuo agente ed esegui i comandi in un terminale (macOS, Linux o Git Bash su Windows) dalla radice del progetto.
Incolla il prompt in Claude, Codex o un altro assistente: controllerà lo skill e lo installerà.
Install the “ask-sonner” skill from mozgi.io (https://mozgi.io/skills/emilkowalski-ask-sonner/) for me. 1. Download the archive: https://mozgi.io/skills/emilkowalski-ask-sonner/download If it fails, take the skill folder from the source: https://github.com/emilkowalski/skills/tree/main/skills/ask-sonner 2. Read SKILL.md and the other files. Check the skill is safe: no hidden commands, no sending data elsewhere, no scripts doing something other than described. If anything looks suspicious, stop and tell me. 3. Put the “ask-sonner” folder into your agent's skills folder: .claude/skills/ for Claude Code, .agents/skills/ for Codex, .cursor/skills/ for Cursor, .gemini/skills/ for Gemini CLI. Inside the project if we are in one, otherwise in the home folder (~/.claude/skills/ etc.). 4. Make sure <skills folder>/ask-sonner/SKILL.md exists. 5. Briefly tell me what this skill does and offer to try it on my task. If you cannot do a step yourself, tell me what to click or type.
git clone --depth 1 --branch main https://github.com/emilkowalski/skills.git /tmp/skills mkdir -p .claude/skills cp -r /tmp/skills/skills/ask-sonner .claude/skills/ask-sonner
Riavvia Claude Code: lo skill compare nell'elenco; per richiamarlo a mano usa /ask-sonner. Per tutti i progetti: ~/.claude/skills.
git clone --depth 1 --branch main https://github.com/emilkowalski/skills.git /tmp/skills mkdir -p .agents/skills cp -r /tmp/skills/skills/ask-sonner .agents/skills/ask-sonner
Codex cerca gli skill in .agents/skills dalla cartella corrente fino alla radice del repo; richiamalo con /skills o $ask-sonner. Per tutti i progetti: ~/.agents/skills.
git clone --depth 1 --branch main https://github.com/emilkowalski/skills.git /tmp/skills mkdir -p .cursor/skills cp -r /tmp/skills/skills/ask-sonner .cursor/skills/ask-sonner
Cursor carica lo skill all'avvio; richiamalo con “/” nella chat Agent. Cursor legge anche .claude/skills e .agents/skills. Per tutti i progetti: ~/.cursor/skills.
git clone --depth 1 --branch main https://github.com/emilkowalski/skills.git /tmp/skills mkdir -p .gemini/skills cp -r /tmp/skills/skills/ask-sonner .gemini/skills/ask-sonner
Gemini CLI propone di attivare lo skill quando il compito corrisponde: tu confermi. Per tutti i progetti: ~/.gemini/skills.
Leggi SKILL.md e i file correlati prima di installare. Clicca un file per l'anteprima.
Contenuto di SKILL.md
Testo originale dell'autore · sola letturaWorking With Sonner
Initial Response
When this skill is first invoked without a specific question, respond only with:
> I'm ready to help you set up, style, and troubleshoot Sonner, my knowledge comes from its author, Emil Kowalski.
Do not provide any other information until the user asks a question.
A guide skill for Sonner ↗, the toast library. When a task involves Sonner — wiring it up, rendering toasts, styling them, or fixing them — answer from this file first. Full prop tables for <Toaster /> and toast() live in API.md ↗; read it when you need an exact prop name, type, or default.
Setup
Two pieces, and only two:
1. One <Toaster />, mounted once, as close to the root as possible (in Next.js: layout.tsx — it works inside server components). Never render it per-page or conditionally; a second mounted Toaster duplicates every toast.
2. toast() called from client code — event handlers, effects, callbacks. It's a plain function, no hook or provider needed, but it does nothing on the server: in a server action, return the result and call toast() in the client code that receives it.
import { Toaster } from 'sonner'; // once, in layout
import { toast } from 'sonner'; // anywhere client-side
Picking the right call
| You want | Call |
| --- | --- |
| Plain message | toast('Title') — add { description } for a second line |
| Success / error / info / warning icon | toast.success('…'), toast.error('…'), etc. |
| Spinner while you manage state yourself | toast.loading('…'), then update it by id |
| Loading → success/error tied to a promise | toast.promise(promise, { loading, success, error }) — success/error accept functions receiving the resolved value/error |
| Button that does something | { action: { label, onClick } } — closes the toast unless onClick calls event.preventDefault(); cancel is the secondary variant |
| Custom JSX, default toast shell | toast(<jsx />) |
| Custom JSX, no styles at all | toast.custom((t) => <jsx />) — headless, t gives you the id to dismiss |
Recipes
Update a toast — call toast() again with the same id; only the props you pass change. Switching to toast.success(…, { id }) changes the type. This is how loading → success flows work without toast.promise:
const id = toast.loading('Uploading…');
toast.success('Uploaded', { id });
Persist — { duration: Infinity }. Dismiss — toast.dismiss(id), or toast.dismiss() for all. Read active toasts — useSonner() in React, toast.getActiveToasts() outside it.
Links or components in the text — pass a function for the title or description: toast(() => <a href="…">View</a>).
Multiple toasters — give each an id and target with toast('…', { toasterId: 'canvas' }). Without toasterId, every toaster renders the toast.
Close callbacks — onDismiss fires on close button or swipe; onAutoClose fires on timeout. They are separate; there is no single "closed" callback.
Styling — the escalation ladder
Climb only as far as the change requires; jumping to the top rung too early is fine (it's the recommended end state), lingering in the middle is not.
1. Defaults — plus richColors on the Toaster for colorful success/error, invert to flip against the theme.
2. Inline tweaks — toastOptions={{ style: {…} }} on the Toaster for all toasts, or style per toast() call.
3. Classes on parts — toastOptions={{ classNames: { toast, title, description, actionButton, cancelButton, closeButton } }}. Sonner's injected styles win the cascade, so every class needs !important (Tailwind: !text-red-900). If you're marking more than a few things important, stop — go headless.
4. Headless — toast.custom() with your own JSX, keeping Sonner's positioning, stacking, and swipe. The recommended approach for a design-system toast: wrap it in your own toast() abstraction. (unstyled: true exists as a halfway house, but headless gives more control for the same effort.)
Icons — swap defaults per-type with the Toaster's icons prop, per-toast with icon, remove with null.
Theme — theme defaults to 'light' and does not track the OS. Pass theme="system", or wire your theme provider: <Toaster theme={resolvedTheme} /> from next-themes.
Troubleshooting
| Symptom | Cause → fix |
| --- | --- |
| Toast never appears | No <Toaster /> mounted, or it unmounted (conditional render, per-page placement). Mount one at the root. If calling from a server action: toast() is client-only — call it with the action's result on the client. |
| Same toast appears twice | Two Toasters mounted (layout and page) — keep one. Or toast() fired in an effect under React StrictMode's dev double-invoke — fire from the event handler instead, or pass a stable id so the second call updates rather than duplicates. |
| Tailwind/CSS classes have no effect | Default styles override them. Mark them !important, or use unstyled / headless (see the ladder above). |
| Toasts render completely unstyled (common in Astro, view transitions) | Sonner's injected stylesheet was lost — import it explicitly in a layout: import 'sonner/dist/styles.css'. |
| Unstyled inside Shadow DOM | Styles land in document.head, not the shadow root. Copy the style tag whose text includes [data-sonner-toaster] into the shadow root. |
| Toast behind a modal/overlay, or clipped | An ancestor creates a stacking context (transform, filter, overflow) or the overlay out-z-indexes the toaster. Move <Toaster /> to the document root, outside any dialog/portal container. |
| Dark mode ignored | theme defaults to 'light' — set theme="system" or pass the resolved theme (see Theme above). |
| Success/error look gray, not green/red | That's the default. Add richColors to the Toaster. |
| Toast never closes | duration: Infinity, dismissible: false, or a toast.promise whose promise never settles — the loading toast waits forever. |
| toast.promise stuck on loading | It needs a promise (or a function returning one) as its first argument, and the promise must actually resolve/reject. |
| Swipe-to-dismiss goes the wrong way / doesn't work | Directions derive from position. Override with swipeDirections on the Toaster. |
| Toast shows up in every toaster | Multiple toasters need targeting: give each Toaster an id and pass toasterId in the toast() call. |
| Toasts too close to the screen edge on mobile | offset (desktop, default 32px) and mobileOffset (<600px, default 16px) — numbers, CSS strings, or per-side objects. |
Domande frequenti
Che cosa fa lo skill ask-sonner?
Guida a Sonner, libreria di notifiche React - installazione e collegamento di Toaster, scelta della corretta chiamata toast(), promesse e caricamento delle notifiche, aggiornamento, annullamento e salvataggio delle notifiche, stilizzazione, temi e icone, posizionamento e più Toaster. Utilizzare durante il lavoro con Sonner o la risoluzione dei problemi - notifiche che non appaiono, appaiono due volte, perdono gli stili, ignorano le classi Tailwind, si trovano dietro una finestra modale o non seguono il tema scuro.
Come si installa ask-sonner?
Apri il blocco “Installazione” in questa pagina e scegli il tuo agente — Claude Code, Codex, Cursor o Gemini CLI — per i comandi pronti che copiano la cartella dello skill nel posto giusto. Oppure copia il prompt dalla scheda “Con l'assistente” e lascia che sia l'assistente a controllare e installare lo skill.
Con quali modelli AI funziona ask-sonner?
Gli skill sono semplici istruzioni in Markdown (formato Agent Skills), quindi ask-sonner funziona con qualsiasi agente che legge SKILL.md: Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode e altri. Il modello carica le istruzioni solo quando il compito corrisponde alla descrizione dello skill.
ask-sonner è gratuito?
Lo skill è pubblicato apertamente da emilkowalski con licenza MIT. Lo skill in sé non costa nulla: paghi solo il tuo fornitore AI per i token usati.
È sicuro installare gli skill?
Uno skill è un insieme di istruzioni che il tuo agente seguirà: leggi SKILL.md e i file correlati prima di installarlo. Gli script nella cartella dello skill vengono eseguiti solo se li esegue l'agente: controlla cosa fa e non concedere permessi superflui.
In cosa differisce uno skill da un server MCP o da un plugin?
Un server MCP o un plugin danno al modello nuovi strumenti: codice che viene eseguito e restituisce un risultato. Uno skill fornisce conoscenza e metodo: come affrontare il compito, quali passi seguire e com'è un buon risultato. Non servono server né chiavi API.