Dialog
阻断当前流程以确认或完成任务。中文惯用名:模态框。设计文档原名:Modal。
稳定本期新增已接入
元信息
| 字段 | 值 |
|---|---|
| 规范 ID | component.dialog |
| 名称 | Dialog |
| 二级分类 | 反馈(feedback) |
| 用途 | 阻断当前流程以确认或完成任务 |
| 描述 | 中文惯用名:模态框。设计文档原名:Modal。 |
预览
静态结构:经 Base UI Dialog 原语渲染——trigger 提供时(非受控用法)以 <span data-slot="dialog-trigger-wrap"> 包装 DSL 子树接入 DialogTrigger,点击打开;弹层经 Portal 挂到 body:遮罩(data-slot="dialog-overlay",fixed inset-0 z-50、半透明覆盖色)+ 内容面板(data-slot="dialog-content",fixed 居中、max-w-lg、rounded-lg + 边框 + 阴影,右上角内置 X 关闭按钮,data-slot="dialog-close");面板内 title / description 渲染标题区(data-slot="dialog-header" 下的 dialog-title / dialog-description,二者均缺省时不渲染),children 紧随其后。X / 遮罩 / Escape 任一途径关闭都走 onOpenChange(false):非受控时内部状态自管理,受控时只回调 onClose。
DSL 结构
{
"type": "Dialog",
"props": {
"title": "编辑成员",
"description": "修改后将立即生效",
"trigger": {
"type": "Button",
"props": {
"text": "打开对话框",
"variant": "primary"
}
}
},
"children": [
{
"type": "Text",
"props": {
"text": "在这里放置表单或其他内容子树;关闭(X / 遮罩 / Escape)由组件内部状态自管理。"
}
}
]
}何时用
何时使用
- 阻断当前流程以确认或完成任务:删除确认、提交前复核等必须先处理完才能继续的操作。
- 承载需要专注的小型表单或决策:信息量与交互控件有限,一屏内可完成。
- 需要明确的「取消 / 确认」二元出口,且弹层期间背景内容不可操作。
何时不用
- 只需就近的轻量「是 / 否」确认:使用 Popconfirm(不打断页面上下文)。
- 在保留页面上下文的同时展示大表单 / 长详情:使用 Drawer(侧滑,不完全遮挡内容)。
- 纯信息补充、可随时忽略:使用 Popover(不阻断,点击外部即关)。
- 破坏性操作未经确认就直接执行:破坏性操作必须先经 Dialog 或 Popconfirm 二次确认。
变体
| 变体 | 视觉形态 | 适用场景 |
|---|---|---|
| 非受控(trigger 触发) | trigger DSL 子树(通常 Button)点击打开,关闭由内部状态自管理 | 触发器与弹层同处的常规用法 |
| 受控 open | open 绑定表达式,关闭时经 onClose 写回 | 需与页面状态联动(提交成功、路由变化)时关闭弹层 |
| 仅标题 | 省略 description,标题区只有一行 | 后果自明的确认(如「确认放弃编辑?」) |
| 标题 + 说明 | dialog-title + dialog-description 两行 | 需要补充后果说明或操作前提 |
| 无标题区(仅内容) | title / description 均缺省,不渲染 header | 内容自带标题的纯内容弹层(如预览、代码片段) |
API 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | string | — | 对话框标题,渲染为 DialogTitle |
description | string | — | 辅助说明,渲染为 DialogDescription(与 title 同时缺省时不渲染标题区) |
open | boolean | — | 受控开关(可绑 ${state.x} 表达式);缺省时由 trigger 自管理内部状态 |
onClose | () => void | — | 关闭事件(X / 遮罩 / Escape 任一途径关闭时触发;Renderer 绑定 events.onClose) |
trigger | DslNode | — | 触发元素(DSL 子树,非受控用法下点击打开) |
children | ReactNode | — | 内容(DSL 子树,经 Renderer children 机制渲染) |
className / style | string / CSSProperties | — | 通用:弹层内容根节点 class 合并 / 内联样式 |
使用规范
- 破坏性操作必须在 Dialog(或 Popconfirm)中二次确认,确认按钮文案写动词(「删除」)而非默认「确定」。
- 标题写问题(「删除这 3 条记录?」)、说明写后果(「删除后不可恢复」);正文承载表单时保持一屏内可完成。
- 关闭途径(X / 遮罩 / Escape)都会触发 onClose:受控用法必须在此把 open 写回 false,否则弹层关不掉。
- 同一时刻只保留一个 Dialog:不要在 Dialog 内再叠 Dialog,多步流程改为分步或改用 Drawer。
- 弹层期间背景不可操作:不要把必须参照背景内容才能完成的任务放进 Dialog。
正例
- ✓ 删除确认:title「删除该成员?」、description 说明后果,trigger 为行内「删除」按钮。
- ✓ 提交前复核:弹层内放表单子树,提交成功后经 onClose 关闭并刷新列表。
- ✓ 受控用法:open 绑定表达式、events.onClose 触发 setState 写回 false,供业务在提交成功时主动关闭。
反例
- ✕ 用 Dialog 承载需要大量滚动与填写的大表单(应使用 Drawer)。
- ✕ 受控用法只绑 open 而不处理 onClose,导致 X 与 Escape 关不掉。
- ✕ 在 Dialog 内再叠一层 Dialog 做二次确认(层级与焦点混乱,应先关闭再确认)。
Design Token 映射
不适用:组件 tokenRefs 为空:样式 Token 数据尚未接入,三层映射(Primitive → Semantic → Component)待样式 Token 接入后回填。