mcpField
A
ask-sonner

ask-sonner

github.com/emilkowalski设计与 UI51.1k146.0k 次安装今天更新
代码仓库

关于 ask-sonner

ask-sonner 是面向 Sonner 使用者的指南技能,涵盖接入、提示样式和故障排查,并提供具体 API 细节的查阅指引。

主要功能

  1. 01Sonner 安装与调用指导
  2. 02提示类型与 Promise 流程
  3. 03样式、主题与图标定制
  4. 04重复显示与定位问题排查

适用场景

  1. 01在 React 应用中接入 Sonner
  2. 02实现加载后更新为成功或错误提示
  3. 03调整提示外观或主题
  4. 04排查提示未显示、重复或被遮挡

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/emilkowalski/skills --skill ask-sonner

安装后在 Claude Code 中输入/ask-sonner确认已加载。

附带文件API.md

详细介绍

使用 Sonner

初次响应

首次调用此技能且未提出具体问题时,只回复:

我已准备好帮助你设置、设置样式和排查 Sonner 问题,我的知识来自其作者 Emil Kowalski。

在用户提问前,不要提供任何其他信息。

这是 Sonner(toast 通知库)的指南技能。任务涉及 Sonner(接入、渲染 toast、设置样式或修复问题)时,优先依据此文件回答。<Toaster /> 和 toast() 的完整属性表位于 API.md;需要确切的属性名称、类型或默认值时,请阅读该文件。

设置

只需两部分:

  1. 挂载一个 <Toaster />,且只挂载一次,并尽可能靠近根节点(在 Next.js 中:layout.tsx——它可以在服务端组件中使用)。不要按页面挂载,也不要有条件地挂载;挂载第二个 Toaster 会导致每条 toast 重复显示。
  2. 在客户端代码中调用 toast()——例如事件处理程序、effect 和回调。这是一个普通函数,不需要 hook 或 provider,但它在服务端不会执行任何操作:在服务端操作中,返回结果,并在接收结果的客户端代码中调用 toast()。
import { Toaster } from 'sonner'; // once, in layout
import { toast } from 'sonner';   // anywhere client-side

选择合适的调用方式

你想要的效果调用方式
普通消息toast('Title')——添加 { description } 可显示第二行
成功/错误/信息/警告图标toast.success('…')、toast.error('…') 等
自行管理状态时显示加载指示器toast.loading('…'),然后通过 id 更新
与 Promise 关联的加载 → 成功/错误toast.promise(promise, { loading, success, error })——success/error 可以接受函数,并接收已解析的值/错误
执行操作的按钮{ action: { label, onClick } }——除非 onClick 调用 event.preventDefault(),否则会关闭 toast;cancel 是次要样式
自定义 JSX,保留默认 toast 外壳toast(<jsx />)
自定义 JSX,不应用任何样式toast.custom((t) => <jsx />)——无头模式,t 会提供可用于关闭 toast 的 id

示例

更新 toast——再次调用 toast() 并传入相同的 id;只有传入的属性会更改。改用 toast.success(…, { id }) 会更改类型。无需使用 toast.promise,即可实现加载 → 成功流程:

const id = toast.loading('Uploading…');
toast.success('Uploaded', { id });

保持显示——{ duration: Infinity }。关闭——toast.dismiss(id),或用 toast.dismiss() 关闭全部。读取活动中的 toast——在 React 中使用 useSonner(),在 React 之外使用 toast.getActiveToasts()。

在文本中添加链接或组件——为标题或描述传入一个函数:toast(() => <a href="…">View</a>)。

多个 toaster——为每个 toaster 指定一个 id,并使用 toast('…', { toasterId: 'canvas' }) 指定目标。不传入 toasterId 时,每个 toaster 都会渲染该 toast。

关闭回调——关闭按钮或滑动关闭时会触发 onDismiss;超时关闭时会触发 onAutoClose。它们是两个独立回调;没有统一的“已关闭”回调。

样式设置 — 逐级升级

只升级到满足改动需求的级别;过早直接跳到最高一级也没问题(这是推荐的最终方案),但不要停留在中间级别。

  1. 默认设置 — 在 Toaster 上启用 richColors,让成功/错误提示显示鲜艳颜色;使用 invert 可反转主题效果。
  2. 内联微调 — 在 Toaster 上使用 toastOptions={{ style: {…} }} 设置所有提示,或在每次 toast() 调用中单独设置 style。
  3. 为各部分添加类名 — 使用 toastOptions={{ classNames: { toast, title, description, actionButton, cancelButton, closeButton } }}。Sonner 注入的样式在层叠中优先级更高,因此每个类都需要 !important(Tailwind:!text-red-900)。如果有好几个地方都要加 !important,就别再继续了——改用无头模式。
  4. 无头模式 — 使用 toast.custom() 和自定义 JSX,同时保留 Sonner 的定位、堆叠和滑动手势。对于设计系统中的提示,推荐将其封装在自己的 toast() 抽象中。(unstyled: true 是折中方案,但无头模式能以相同的工作量提供更多控制。)

图标 — 使用 Toaster 的 icons 属性按类型替换默认图标;使用 icon 按提示单独设置;设为 null 可移除图标。

主题 — theme 默认为 'light',不会跟随操作系统主题。传入 theme="system",或接入主题提供程序:使用 next-themes 中的 <Toaster theme={resolvedTheme} />。

故障排查

现象原因 → 解决方法
提示从未出现没有挂载 <Toaster />,或者它已被卸载(条件渲染、按页面放置)。请在根节点挂载一个。如果从服务端操作中调用:toast() 只能在客户端使用——在客户端根据操作结果调用它。
同一条提示出现两次挂载了两个 Toaster(布局和页面各一个)——保留一个即可。或者在 React StrictMode 开发环境的双重调用下,toast() 在 effect 中触发了两次——改为从事件处理程序中触发,或传入稳定的 id,让第二次调用更新提示而不是重复创建。
Tailwind/CSS 类不起作用默认样式覆盖了它们。为其添加 !important,或使用 unstyled/无头模式(见上方逐级升级说明)。
提示完全没有样式(Astro、视图过渡中常见)Sonner 注入的样式表丢失了——在布局中显式导入:import 'sonner/dist/styles.css'。
Shadow DOM 中没有样式样式会写入 document.head,而不是 shadow root。将文本包含 [data-sonner-toaster] 的 style 标签复制到 shadow root 中。
提示被模态框/覆盖层遮挡,或被裁切某个祖先元素创建了堆叠上下文(transform、filter、overflow),或覆盖层的 z-index 高于 toaster。将 <Toaster /> 移到文档根节点,置于所有对话框/portal 容器之外。
深色模式未生效theme 默认为 'light'——设置 theme="system",或传入解析后的主题(见上方主题说明)。
成功/错误提示显示为灰色,而不是绿色/红色这是默认效果。在 Toaster 上添加 richColors。
提示一直不关闭duration: Infinity、dismissible: false,或 toast.promise 对应的 promise 一直未结束——加载提示会一直等待。
toast.promise 一直处于加载状态它的第一个参数必须是一个 promise(或一个返回 promise 的函数),并且该 promise 必须实际完成或拒绝。
滑动关闭方向错误/无法使用方向由 position 决定。使用 Toaster 上的 swipeDirections 覆盖。
提示出现在每个 toaster 中多个 toaster 需要指定目标:为每个 Toaster 设置 id,并在 toast() 调用中传入 toasterId。
移动设备上提示离屏幕边缘太近使用 offset(桌面端,默认值为 32px)和 mobileOffset(<600px,默认值为 16px)——可使用数字、CSS 字符串或按边设置的对象。

评论

支持 Markdown