对话框
使用方法
Dialog 在页面内容上方呈现一个模态对话框,用来承载需要用户专注处理的任务。它基于原生 <dialog> 元素,会自动锁定背景、把焦点限制在对话框内,关闭后焦点还会还给打开它的元素。搭配 DialogHeader 使用,可以获得可聚焦的标题、可选的副标题和关闭按钮:
<script setup lang="ts">
import { Button } from '@astryx-vue/core/Button'
import { Dialog, DialogHeader } from '@astryx-vue/core/Dialog'
import { ref } from 'vue'
const isOpen = ref(false)
</script>
<template>
<Button label="分享项目" variant="secondary" @click="isOpen = true" />
<Dialog :is-open="isOpen" @open-change="isOpen = $event">
<DialogHeader title="分享项目" has-close-button @open-change="isOpen = $event" />
<p>复制链接并发送给团队成员。</p>
</Dialog>
</template>最佳实践
| 指引 | 实践 |
|---|---|
| 推荐 | 选择正确的用途:info 用于可关闭的内容,form 用于防止误点遮罩关闭,required 用于必须由用户作出响应的场景。 |
| 推荐 | 在头部添加清晰的标题,让用户立即了解对话框要他们做什么。 |
| 推荐 | 含有输入内容的对话框使用 purpose="form"。这样用户不会因误点遮罩而丢失数据。 |
| 推荐 | 对话框只处理单一任务。内容超出可容纳范围时,考虑改用整页。 |
| 避免 | 用对话框展示简单消息。这类消息可以内联显示,或使用 Toast 通知。 |
| 避免 | 在对话框中嵌套对话框。应把流程拆成单个对话框内的多个步骤。 |
| 避免 | 为简单确认使用 fullscreen 变体。它适用于编辑器或长表单等复杂内容。 |
示例
基本用法
包含副标题与关闭按钮的标题区。对话框打开时标题获得焦点。
表单
purpose 为 form 时允许 Escape 关闭,但忽略点击遮罩,避免已输入的内容意外丢失。
必须响应
purpose 为 required 时禁用 Escape 与点击遮罩关闭。用户必须做出选择时使用 alertdialog 语义。
全屏
variant 为 fullscreen 时占满视口,适合长篇编辑任务,并尊重安全区域。
命令式
useImperativeDialog 无需管理 isOpen 即可打开内容。在模板中渲染一次它的 Host。
无障碍
Dialog 基于原生 <dialog> 元素构建,模态行为、焦点限制和关闭后的焦点归还都由浏览器提供,因此不需要额外配置就能获得正确的无障碍表现。
对话框通过 showModal() 打开,打开期间页面其余部分不可交互。打开后,初始焦点落在第一个带有 data-autofocus 的元素上;如果没有元素带这个属性,焦点落在 DialogHeader 的标题上。
对话框的名称默认取自 DialogHeader 的标题,组件会把标题与对话框通过 aria-labelledby 关联起来。如果显式设置了 aria-label 或 aria-labelledby,则以你提供的名称为准。
Escape 与点击遮罩不会直接关闭对话框,它们只发出 openChange(false),由父组件决定是否关闭。关闭后,如果打开对话框之前的那个元素仍在页面中,焦点会回到它身上。
限制
下面两点决定了你能在对话框里放什么内容,在组合 Tooltip、Popover 或多步流程之前需要先了解。
- Tooltip 与 Popover 会渲染到
body。在打开的Dialog内使用时,它们位于模态顶层之下,因此既看不到也无法操作;在它们获得对话框自身的层级之前,请不要把它们嵌套进对话框。 - 对话框不可嵌套。需要多步流程时,请把流程拆分为同一个对话框内的步骤。
布局
标准变体通过 width 与 maxHeight 定尺寸,在窄屏上以间距令牌为边距夹取到视口内。position 设置静态偏移;逻辑属性 start 与 end 在 RTL 下自动镜像。