Snackbar 消息条
在不打断当前流程的前提下给出一条简短反馈:保存成功、邮件已归档、网络异常。它浮在页面底部居中, 自动消失,或者让用户点「撤销」这类操作。
- 反色表面:浅色主题里是深色条、深色主题里反过来(
bg-ds-fg+text-ds-bg),保证消息永远从背景里跳出来。 - 一屏只有一条;后来的排队,上一条离场动画结束才轮到下一条。
- 两种用法:模板里声明
Snackbar+v-model:open,或在任何地方调用showSnackbar(),不需要组件树。
声明式:最小用法
v-model:open 是唯一的显示状态来源,duration(默认 5000ms)到了组件会把 open 置回 false。 给 0 就变成常驻,只能由用户关闭。
vue
<script setup lang="ts">
import { ref } from "vue";
import { Button, Snackbar } from "@sharpdotnut/dotsharp";
const open = ref(false);
</script>
<template>
<Button @click="open = true">保存</Button>
<Snackbar v-model:open="open" text="更改已保存" />
</template>带操作按钮
action 是按钮文案,点击后触发 action 事件并关闭消息。操作是「撤销」「重试」这类可以立刻执行的补救动作, 不要在这里放次要的「了解更多」——那是对话框或链接的职责。
最近一次操作:—
vue
<script setup lang="ts">
import { ref } from "vue";
import { Button, Snackbar } from "@sharpdotnut/dotsharp";
const open = ref(false);
function undo(): void {
// 撤销归档
}
</script>
<template>
<Button @click="open = true">归档</Button>
<Snackbar v-model:open="open" text="邮件已归档" action="撤销" @action="undo" />
</template>需要给操作加图标或自定义内容时用 action 插槽,它优先于 action 属性。
常驻与关闭按钮
duration="0" 关掉自动关闭;再打开 dismissible 显示右上角的关闭按钮(无障碍名称由 close-label 提供, 默认 Close)。用于「有未保存的修改」这类必须让用户看见并处理的状态。
vue
<Snackbar v-model:open="open" text="有未保存的修改,离开前请先保存" :duration="0" dismissible />函数式调用
showSnackbar(options) 在任何地方都能用——事件回调、请求拦截器、路由守卫——它在首次调用时才把宿主挂到 body,引入模块本身没有副作用。返回的句柄带 close(),可以提前关掉这一条。
撤销次数:0 撤销只对被点的那一条生效。
ts
import { showSnackbar } from "@sharpdotnut/dotsharp";
showSnackbar({
text: "邮件已归档",
action: { label: "撤销", onAction: () => restore() },
});
// 句柄可以提前关闭;还在排队时直接从队列移除。
const handle = showSnackbar({ text: "正在上传…", duration: 0, dismissible: true });
handle.close();
// 路由切换这类时机一键清场。
closeAllSnackbars();连续推送三条时只有第一条可见,后两条排队,每条展示 1500ms。
多行与富内容
默认插槽优先于 text,可以塞进换行或强调文本;消息条本身不限行数,但超过两行就该考虑改用对话框。
vue
<Snackbar v-model:open="open" :duration="0" dismissible>
已从「草稿箱」删除 3 个会话
<span class="text-ds-bg/70">(可在 30 天内从回收站恢复)</span>
</Snackbar>API
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| v-model:open | boolean | false | 是否显示;超时后组件自己置回 false |
| text | string | — | 正文;默认插槽优先 |
| action | string | — | 操作按钮文案;action 插槽优先 |
| duration | number | 5000 | 自动关闭的毫秒数;0 表示常驻 |
| dismissible | boolean | false | 是否显示关闭按钮 |
| closeLabel | string | "Close" | 关闭按钮的无障碍名称 |
事件与插槽
| 名称 | 说明 |
|---|---|
action | 操作按钮被点击;随后消息自动关闭 |
default | 正文,优先于 text |
action | 操作按钮的内容,优先于 action 文案 |
showSnackbar
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| text | string | — | 正文(必填) |
| action | SnackbarAction | — | { label, onAction? } |
| duration | number | 5000 | 0 表示常驻 |
| dismissible | boolean | false | 是否显示关闭按钮 |
| closeLabel | string | "Close" | 关闭按钮的无障碍名称 |
返回 { id, close };另外导出 closeAllSnackbars() 清空当前消息与队列。
可访问性
- 消息条根元素是
role="status"+aria-atomic="true",出现时读屏会礼貌播报整条内容。 - 关闭按钮是纯图标,必须有
closeLabel;操作按钮是普通按钮,键盘可聚焦,焦点环使用反色前景。 - 消息条不会抢焦点,也不阻断页面交互——这正是它和对话框的分界。
- 常驻消息(
duration="0")要把用户能做的动作一起给出,否则读屏用户与键盘用户会被一条关不掉的消息困住。