Toast
toast用命令式调用弹出会自动消失的轻提示
用法
基础用法
命令式调用 toast(),页面任意处可调(需单挂一个 <ToastProvider/>)。
tsx
toast({ title: "已复制到剪贴板" });五语调
tone 提供 neutral / info / success / warning / danger,与 Alert 对齐,驱动左边条与标题着色。
tsx
toast({ title: "已复制到剪贴板" }); // neutral
toast({ tone: "info", title: "有新版本", description: "点击刷新以更新。" });
toast({ tone: "success", title: "已保存", description: "更改已同步到云端。" });
toast({ tone: "warning", title: "部分失败", description: "3 条中 1 条未同步。" });
toast({ tone: "danger", title: "保存失败", description: "网络异常,请重试。" });常驻不自动消失
timeout=0 时不自动关闭,需手动点 × 关闭。
tsx
toast({ title: "需手动关闭", description: "timeout=0,点 × 才消失。", timeout: 0 });堆叠
连续调用堆叠展示(Provider 默认限 3 条)。
tsx
toast({ tone: "info", title: "第 1 条" });
toast({ tone: "neutral", title: "第 2 条" });
toast({ tone: "danger", title: "第 3 条" });何时用
操作后命令式弹出的轻提示(已保存、已复制、保存失败),自动消失、队列堆叠(limit 3)。静态常驻的区块内提示用 Alert;横贯顶部的公告 bar 用 Banner;需要展开操作/富内容的通知用 Notification。ToastProvider 在应用/段落 layout 单挂一次,业务侧只调 toast()。
导入
ts
import { toast, ToastProvider } from "@hulianui/ui"Props
toast(options) 的 ToastOptions:
ToastProvider 的 ToastProviderProps:
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| position | "top-left"|"top-center"|"top-right"|"bottom-left"|"bottom-center"|"bottom-right" | "top-right" | 视口停靠位置。底部三档队列改成从下往上堆(最新一条永远贴着停靠边),入场滑动方向也跟着换手。全局值,单条 toast 不能各挑各的 |
伴生函数
| 名称 | 签名 | 说明 |
|---|---|---|
toast.close | (id?: string) => void | 按 toast() 返回的 id 关掉某一条;不传 id 关掉全部。走正常出场过渡,不是硬拔 DOM |
Slots
toast(options) 的 ToastOptions:
| 插槽 | 类型 | 说明 |
|---|---|---|
| title | ReactNode | 标题(加粗主行) |
| description | ReactNode | 描述(次行,恒 text-muted-foreground) |
ToastProvider 在根/段落 layout 单挂,承接命令式渲染。children 可选且透传渲染:包裹式 <ToastProvider><App/></ToastProvider> 与自闭合 <ToastProvider />(与页面内容并列兄弟)两种写法均可。
禁忌 / 坑
ToastProvider全应用只挂一次(在段落 layout),别在 showcase/页面里重复挂,否则命令式渲染会重复。- `loading` 不是「第六档 tone」:它与
tone正交,进行中的提示照样可以是neutral/info。它只做两件事——渲转圈图标、把timeout的缺省值从 5000 改成 0。 loading与timeout: 0不是两套常驻语义,是同一个timeout的默认值之差:显式传timeout依然优先,{ loading: true, timeout: 3000 }就是 3 秒后自己走。loading恒走priority: "low"(polite),即使同时传tone: "danger"也不升 assertive:「进行中」是陪跑不是结果,而且这条会长时间挂着,assertive 会反复插队打断读屏正在念的内容。- 开了
loading就必须自己 `toast.close(id)`,否则它永远不走。别指望用户去点 ×——「进行中」本来就该由代码收尾。 - 转圈图标在
prefers-reduced-motion: reduce下是减速到 2.4s 一圈,不是停转(库内装饰性动效统一走[animation:none],这里有意不同):这个圈是「进行中」在视觉上唯一的记号,定格成静止圆弧就跟普通装饰图标没区别,状态信息当场消失。 @hulianui/ui< 0.8 的ToastProvider不渲染 children:包裹式写法会静默吞掉整个应用子树(白屏、零报错)。0.8 起已修复为透传渲染;旧版本务必用自闭合写法。@hulianui/ui≤ 0.8 的ToastTone只有info | danger | neutral,成功/警告态只能降级成info/neutral;0.8 之后已补齐success/warning,升级后可直接换回语义正确的 tone。- 仅
danger走priority: "high"(aria-live assertive 打断播报),warning与其余 tone 一样是 polite——警告不抢读屏焦点是有意为之。 - 测试该组件时注意 Base UI Toast 的几个坑见 [[base-ui-toast-close-aria-hidden-query-dom-not-role]]:未聚焦的 Close 按钮带
aria-hidden致getByRole("button")找不到(改查 DOM)、aria-live 公告会让标题文本重复匹配、全局 manager 持久化致 toast 跨测试泄漏需清理。
相关
Alert · Banner · Notification · ServiceMessage · Result · GiftFeed
Playground
toast({
tone: "neutral",
title: "已保存",
description: "更改已成功同步。",
timeout: 5000,
})