К основному содержанию
скилл Claude Code CX Codex Cursor GitHub Copilot

ask-sonner — скилл для Claude Code: тосты Sonner и установка

Справочник по Sonner, React-библиотеке тостов: подключение, вызовы toast(), стили и разбор поломок.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add emilkowalski/skills --skill ask-sonner -a claude-code
Открыть на GitHub

Что делает ask-sonner

Скилл разбирает Sonner по частям: один ` в корне приложения (layout.tsx в Next.js), а toast() вызывается только из клиентского кода. Внутри есть таблица выбора вызова: обычное сообщение, toast.success с иконкой, toast.loading со своим состоянием, toast.promise со связкой loading/success/error, кнопка через action и cancel, свой JSX в toast.custom. Отдельно оговорено, что в server action toast()` не сработает: сначала верните результат, потом показывайте тост на клиенте.

Дальше идут рецепты: обновление тоста по id, duration: Infinity для постоянных сообщений, toast.dismiss, чтение активных тостов через useSonner() или toast.getActiveToasts(), несколько тостеров с toasterId, раздельные onDismiss и onAutoClose. Стили описаны лестницей от richColors и invert до classNames с !important и headless-варианта. Полные таблицы пропсов лежат в API.md рядом со скиллом.

Самое практичное здесь — список симптомов: тост не появляется, дублируется, теряет стили, не видит Tailwind-классы, уходит за модалку, игнорирует тёмную тему (theme по умолчанию 'light'), зависает на loading. При первом запуске скилл отвечает одной фразой и ждёт конкретного вопроса. Ставить стоит, если вы уже пишете тосты на Sonner или только выбираете, как их делать. Обойтись можно: скилл покрывает Sonner, а не уведомления в продукте вообще.

Какие задачи решает

  • Поднять `` один раз в корне и не плодить дубли в layout и на странице
  • Сделать цепочку loading → success на основе промиса
  • Починить тост, который не появляется после server action
  • Перевести тосты на свою дизайн-систему через toast.custom
  • Заставить тосты следовать тёмной теме приложения

Примеры запросов агенту

  • Подключи Sonner в `app/layout.tsx` и покажи тост после сохранения формы
  • Тост не появляется после server action. В чём причина?
  • Перепиши наши тосты на `toast.custom` со стилями дизайн-системы

Как установить ask-sonner

1Через Skills CLI (Vercel)

npx skills add emilkowalski/skills --skill ask-sonner -a claude-code

2Вручную: положить файлы

~/.claude/skills/ask-sonner/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/ask-sonner/

Из того же набора15

Весь набор →
emil-design-eng emilkowalski Скилл задаёт правила для полировки интерфейсов, компонентов и анимаций. Пригодится, когда UI работает, но требует более точных состояний и переходов. Claude Code CX Codex Cursor +1 385 500установок review-animations emilkowalski Проверяет код интерфейсных анимаций по принципам Эмиля Ковальски. Помогает убрать дерганые переходы, медленный ease-in и лишнюю нагрузку на процессор. Claude Code CX Codex Cursor +1 254 100установок apple-design emilkowalski Переносит принципы физического интерфейса Apple с докладов WWDC в веб на CSS, Pointer Events и Motion. Пригодится при верстке жестов, шторки и прерываемых пружин. Claude Code CX Codex Cursor +1 242 100установок animation-vocabulary emilkowalski Скилл подбирает точный термин для описанной веб-анимации. Пригодится, когда эффект нужно понятно назвать для промпта или дизайнера. Claude Code CX Codex Cursor +1 236 900установок improve-animations emilkowalski Скилл проводит ревизию анимаций в кодовой базе и составляет готовые планы доработок. Помогает найти неудачные тайминги и прыгающие элементы, не меняя код напрямую. Claude Code CX Codex Cursor +1 222 000установок find-animation-opportunities emilkowalski Ищет в коде и интерфейсе места для уместной анимации, а лишние варианты отбрасывает. Подходит для проверки идеи «сделать интерфейс живее». Claude Code CX Codex Cursor +1 206 800установок pick-ui-library emilkowalski Скилл подбирает библиотеку под конкретную задачу фронтенда по списку Эмила Ковальски: тосты, графики, OTP-поля, виртуализация, drag and drop. Запускается только по явному вызову. Claude Code CX Codex Cursor +1 183 400установок prototype emilkowalski Скилл собирает несколько по-настоящему разных вариантов одного куска UI и ставит их за визуальный пикер: переключаете на ходу и выбираете тот, что нравится больше. Claude Code CX Codex Cursor +1 172 400установок

Похожие

migrate-radix-to-base shadcn-ui Переводит компоненты и проекты React с Radix UI на Base UI (@base-ui/react). Пригодится при смене базовой библиотеки в проектах на shadcn/ui. Claude Code CX Codex Cursor +1 30 100установок hallmark Nutlope Задаёт жесткие правила верстки для веб-страниц, чтобы интерфейсы нейросетей не выглядели шаблонными. Нужен при создании нового дизайна или полном редизайне. Claude Code CX Codex Cursor +1 69 100установок design-system claudekit Скилл собирает дизайн-токены, спецификации компонентов и презентационные слайды. Подойдёт, когда интерфейс и слайды должны следовать одной системе. Claude Code CX Codex Cursor +1 42 200установок remotion-best-practices remotion-dev Маршрутизирует задачи Remotion к подходящим инструкциям для создания видео, React-разметки, карт, мультимедиа и рендера. Claude Code CX Codex Cursor +1 678 800установок frontend-design официальный anthropics Скилл задаёт осмысленное визуальное направление для новых интерфейсов и редизайна. Подойдёт, когда стандартный шаблонный UI не устраивает. Claude Code Claude.ai 1 025 790установок design-taste-frontend Leonxlnx Скилл задаёт арт-дирекцию для публичных страниц и рабочих экранов, а затем проверяет результат в браузере по скриншотам. Нужен, когда интерфейс выглядит шаблонным или недоработанным. Claude Code CX Codex Cursor +1 673 100установок prototype Matt Pocock Создаёт временный прототип, чтобы проверить логику, модель состояния или вид интерфейса до работы над основным кодом. Claude Code 986 201установок hyperframes heygen-com Скилл задаёт агенту правила рендера HTML-кода в видео через HyperFrames. Помогает собирать проморолики, эксплейнеры и титры прямо в коде проекта. Claude Code CX Codex Cursor +1 1 200 000установок

Вопросы о ask-sonner

Как установить ask-sonner в Claude Code?

Командой npx skills add emilkowalski/skills --skill ask-sonner -a claude-code. Файл скилла окажется по пути ~/.claude/skills/ask-sonner/SKILL.md.

Что делает ask-sonner?

Служит справочником по Sonner: как подключить тостер, какой вызов toast() выбрать под задачу, как обновлять и закрывать тосты, как их стилизовать и почему они ломаются.

Почему один и тот же тост показывается дважды?

Либо смонтированы два ` (например, в layout и на странице), либо toast() вызван в эффекте, который в dev-режиме StrictMode срабатывает дважды. Вынесите вызов в обработчик события или передайте стабильный id`, чтобы второй вызов обновлял тост, а не добавлял новый.

Исходный текст

SKILL.md · MIT
---
name: ask-sonner
description: Guide to Sonner, the React toast library — install and wire up the Toaster, pick the right toast() call, promise and loading toasts, updating, dismissing and persisting toasts, styling, theming and icons, positioning and multiple toasters. Use when working with Sonner or troubleshooting it — toasts that don't appear, appear twice, lose their styles, ignore Tailwind classes, sit behind a modal, or don't follow dark mode.
---

# Working 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](https://sonner.emilkowal.ski), 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](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.

```jsx
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`:

```jsx
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. |

© emilkowalski · MIT · emilkowalski/skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой