标题写「确认删除「活动报名页」?」,正文写「无法恢复」;主操作危险样式、取消是安全退路;点遮罩不关闭,Esc 可取消;Tab 在弹窗内循环,关闭后焦点回到触发按钮。
先开弹窗,再看焦点和遮罩怎么处理
一台弹窗实验台:切换「删除草稿(破坏性)」和「补充副标题(普通表单)」两个场景,弹窗的标题、说明和主 CTA 会随之改变;打开后按 Tab 看焦点在弹窗内循环,按 Esc 取消,点遮罩看破坏性场景为什么被拦下;确认后结果落在背景记录物件上。
场景
活动报名页(暂无副标题)
默认是破坏性确认场景:点「删除草稿」打开弹窗,焦点会移到「取消」并在弹窗内循环;试着按 Esc、点遮罩,再确认删除看背景记录被移除。
从刚才的操作里提炼
你在实验台上看到的就是 modal 的核心;下面只是把它命名清楚。
- modal 用遮罩 + 焦点陷阱强制一次决策:遮罩盖住背景记录,Tab 在弹窗内循环、关闭后回到触发按钮——背景按钮拿不到焦点,所以它「打断」主流程。
- 标题必须说清做什么、后果是什么:实验台里破坏性场景写「确认删除「活动报名页」?」加「无法恢复」;因为确认后记录真的会被移除,打断要承担代价。
- 遮罩策略随后果分:破坏性操作点遮罩被拦下(误点 ≠ 误删);普通表单点遮罩可关闭(可恢复、不强制)。Esc 在两个场景都是安全出口。
- 主操作与取消要分清:主 CTA「确认删除 / 保存副标题」承担最关键的动作(唯一的 Rausch);取消是安全退路,处理中主 CTA 禁用防连点。
- 结果长在背景物件上:确认删除后背景记录被移除、保存后副标题更新——不是只换一句 status 文案,而是让你看见 modal 造成的真实改变。
什么时候用 modal
从用户信号判断,也要知道它与相邻临时层组件的边界。
- 用:破坏性或不可逆操作前的显式确认,如删除、覆盖、发布、清空。
- 用:必须打断主流程、强制用户聚焦完成的一件小事,如补充关键字段、二次验证、阅读条款后继续。
- 区分 Drawer:Drawer 从侧边滑出、保留列表上下文、可边看边操作;modal 居中遮罩、强制决策、打断主流程。
- 区分 Popconfirm:Popconfirm 是挂在触发器旁的小气泡、只做是/否确认;modal 是独立的全屏遮罩,承载表单、详情、确认等多类内容。
- 区分 Alert:Alert 是页内平级提示条、不打断键盘焦点;modal 用遮罩 + 焦点陷阱强制阻断。
- 不用:成功反馈(用 Toast)、整页结果(用 Result)、可边看边操作的详情(用 Drawer)、简单的就地是/否确认(用 Popconfirm)。
怎么用:从打开到结果的最短路径
让一次弹窗说清对象、后果和退路,并把结果落在背景物件上。
- 打开:由触发动作(如「删除」按钮)打开;打开后焦点移入弹窗,落在最安全的控件(取消或首个输入)。
- 写文案:标题说清「对哪个对象做什么」,正文写后果;主操作与取消视觉区分;危险操作用危险样式 + 文字,不只靠颜色。
- 定遮罩策略:破坏性操作禁止点遮罩关闭;可恢复操作允许点遮罩关闭;Esc 始终可取消。
- 焦点陷阱:Tab 在弹窗内循环、Shift+Tab 反向循环;关闭后焦点回到触发按钮;背景内容用
inert或原生<dialog>真正隔离。 - 处理与结果:确认中禁用主 CTA 防连点;完成后结果落在背景物件上(记录移除 / 数据更新),并关闭弹窗。
- 加语义:容器用
role="dialog"与aria-modal="true",标题aria-labelledby,说明aria-describedby,状态写进aria-live区域。
正反例:同一个删除确认,只改一处
围绕同一个删除草稿场景,只改变「弹窗是否给安全退路并挡住遮罩误点」,看用户后果如何不同。
没有确认步骤,或确认弹窗允许点遮罩关闭且焦点丢失——用户手滑点到遮罩就造成数据丢失,键盘用户也找不到安全出口;删没删成还得靠猜。
快速自测
破坏性确认弹窗最不能省略的两条退路是什么?
继续查证
术语的技术定义和行为以这些一手或权威资料为准。
下一步学
和本知识点经常一起出现的概念。