<script setup lang="ts">
import { ref } from 'vue'
import { AlertDialog, Button, Stack, Text } from '@hina-ui/vue'
const removed = ref(false)
async function remove() {
await new Promise(resolve => setTimeout(resolve, 800))
removed.value = true
}
</script>
<template>
<Stack gap="sm" align="start">
<AlertDialog
title="删除这篇文章?"
description="删除后无法恢复,文章下的评论也会一并删除。"
tone="danger"
confirm-text="删除"
@confirm="remove"
>
<Button variant="outline" tone="danger">删除文章</Button>
</AlertDialog>
<Text v-if="removed" tone="muted" size="sm">文章已删除。</Text>
</Stack>
</template>
vue
用法
import { AlertDialog } from '@hina-ui/vue'
ts
确认对话框只问一个问题:title 是问题本身,description 补充后果,底部固定一对按钮,文字可以用 cancelText 与 confirmText 替换。默认插槽是触发器。点击遮罩不会关闭它,按 Esc 或者点「取消」才会;它没有右上角的关闭按钮,回答本身就是关闭的方式。
<script setup lang="ts">
import { ref } from 'vue'
import { AlertDialog, Button, Stack, Text } from '@hina-ui/vue'
const published = ref(false)
</script>
<template>
<Stack gap="sm" align="start">
<AlertDialog
title="发布这篇文章?"
description="发布之后所有人都能看到它。"
confirm-text="发布"
cancel-text="再想想"
@confirm="published = true"
>
<Button variant="outline" tone="neutral">发布</Button>
</AlertDialog>
<Text v-if="published" tone="muted" size="sm">文章已发布。</Text>
</Stack>
</template>
vue
示例
危险操作
tone="danger" 把「确定」换成危险色,用于删除这类不可撤销的操作。
<script setup lang="ts">
import { AlertDialog, Button } from '@hina-ui/vue'
</script>
<template>
<AlertDialog
title="注销账号?"
description="账号与所有数据会在 30 天后永久删除,期间登录即可撤销。"
tone="danger"
confirm-text="注销"
>
<Button variant="outline" tone="danger">注销账号</Button>
</AlertDialog>
</template>
vue
确认倒计时
confirmDelay 指定确认前的等待秒数,默认为 0。每次打开时重新计时,期间确认按钮禁用并显示剩余秒数;结束后恢复原文案与可点击状态,取消和 Esc 在等待期间仍可用。
打开期间修改 confirmDelay 会按新值重新计时,设为 0 立即解除等待。正小数向上取整,非正数或非有限值按 0 处理。确认失败后可以直接重试。
<script setup lang="ts">
import { AlertDialog, Button } from '@hina-ui/vue'
</script>
<template>
<AlertDialog
title="确认操作?"
description="倒计时结束后,确认按钮可以点击。"
tone="danger"
confirm-text="确认"
:confirm-delay="3"
>
<Button variant="outline" tone="neutral">确认倒计时</Button>
</AlertDialog>
</template>
vue
异步确认
onConfirm 接收确认处理函数,也可以通过 @confirm 传入。返回 Promise 或 PromiseLike 时,对话框等待其完成再关闭:期间「确定」显示加载指示,「取消」与 Esc 都不可用。
同步抛错或异步拒绝由组件内部捕获,并通过 error 事件传出原始错误。对话框保持打开并恢复按钮,可以直接重试;使用 @error 更新错误提示。
<script setup lang="ts">
import { ref } from 'vue'
import { AlertDialog, Button, Stack, Switch, Text } from '@hina-ui/vue'
const fail = ref(false)
const status = ref('')
async function archive() {
status.value = ''
await new Promise(resolve => setTimeout(resolve, 1000))
if (fail.value) {
throw new Error('归档失败,请稍后再试。')
}
status.value = '已归档。'
}
function handleError(error: unknown) {
status.value = error instanceof Error ? error.message : String(error)
}
</script>
<template>
<Stack gap="md" align="start">
<Switch v-model="fail">模拟失败</Switch>
<AlertDialog
title="归档这个项目?"
description="归档后项目变为只读,可以随时恢复。"
confirm-text="归档"
@confirm="archive"
@error="handleError"
>
<Button variant="outline" tone="neutral">归档项目</Button>
<template #content>
<Text v-if="status" tone="muted" size="sm">{{ status }}</Text>
</template>
</AlertDialog>
</Stack>
</template>
vue
受控
open 支持双向绑定。省略默认插槽时不渲染触发器,对话框只能从外部打开。
<script setup lang="ts">
import { ref } from 'vue'
import { AlertDialog, Button, Inline } from '@hina-ui/vue'
const open = ref(false)
</script>
<template>
<Inline gap="sm">
<Button variant="outline" tone="neutral" @click="open = true">从外部打开</Button>
<AlertDialog v-model:open="open" title="离开当前页面?" description="未保存的修改会丢失。" />
</Inline>
</template>
vue
尺寸与位置
size 默认 sm,宽 384 像素,md 为 448 像素;placement 与 Dialog 相同,不设置时宽屏居中、窄屏贴底。
<script setup lang="ts">
import { AlertDialog, Button, Inline } from '@hina-ui/vue'
</script>
<template>
<Inline gap="sm">
<AlertDialog title="清空回收站?" description="回收站里的 12 个文件会被永久删除。" size="md">
<Button variant="outline" tone="neutral">md 尺寸</Button>
</AlertDialog>
<AlertDialog
title="清空回收站?"
description="回收站里的 12 个文件会被永久删除。"
placement="center"
>
<Button variant="outline" tone="neutral">始终居中</Button>
</AlertDialog>
<AlertDialog
title="清空回收站?"
description="回收站里的 12 个文件会被永久删除。"
placement="bottom"
>
<Button variant="outline" tone="neutral">始终贴底</Button>
</AlertDialog>
</Inline>
</template>
vue
行为
- 打开时焦点落在「取消」按钮上,误按回车不会执行操作;关闭后焦点回到触发器。
- 点击遮罩不关闭;Esc 关闭,等同于取消。
- 打开期间页面停止滚动,焦点被限制在面板内。
- 「确定」的处理函数返回 Promise 时,对话框在其结束前处于忙碌状态,成功后关闭;失败时触发
error并保持打开。
无障碍
- 面板是
role="alertdialog",标题与说明分别关联到aria-labelledby与aria-describedby。 - 忙碌期间面板带有
aria-busy。 - 按钮文字取自当前语言,可以替换。
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | string | — | 必填。问题本身 |
description | string | — | 补充说明 |
confirmText | string | 当前语言 | 「确定」按钮的文字 |
confirmDelay | number | 0 | 每次打开后的确认等待秒数 |
cancelText | string | 当前语言 | 「取消」按钮的文字 |
tone | 'accent' | 'danger' | 'accent' | 「确定」按钮的色调 |
size | 'sm' | 'md' | 'sm' | 面板的最大宽度 |
placement | 'center' | 'bottom' | — | 不设置时随屏幕宽度变化 |
onConfirm | () => unknown | — | 确认处理函数,可返回 Promise 或 PromiseLike |
open | boolean | — | 是否打开,支持双向绑定 |
class | string | — | 追加至面板的类名 |
插槽
| 插槽 | 说明 |
|---|---|
| default | 触发器 |
content | 说明与按钮之间的内容 |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
confirm | — | 点击「确定」;处理函数返回 Promise 时等待其完成 |
cancel | — | 点击「取消」 |
error | unknown | 确认失败的原始错误,弹窗保持打开 |