mcpField
A
ask-sonner

ask-sonner

github.com/blockmatic开发1213 次安装4 周前更新
代码仓库

关于 ask-sonner

用于配置、设置样式和排查 Sonner(通知提示库)的指南 Skill,介绍常见用法,并提供安装与样式建议;需要精确 API 信息时另查参考文档。

主要功能

  1. 01说明 Toaster 配置与 toast 调用
  2. 02介绍成功、加载和 Promise 提示
  3. 03指导提示样式与自定义
  4. 04列出常见问题排查方法

适用场景

  1. 01在应用中接入 Sonner
  2. 02自定义提示的外观与行为
  3. 03排查提示重复或未显示的问题

安装

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

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

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

附带文件API.mdLICENSE.txt

详细介绍

使用 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