跳到正文

Modal 模态框

Modal 在变暗的页面上弹出一个对话框:桌面端是居中的卡片,手机上是底部弹出的面板(bottom sheet),两者是同一个组件。它同时覆盖卡片和对话框两种用法:title、正文、footer 和确认 / 取消按钮;也可以用 raw 自己画外观。

它和 Popover 一样是浮层,而不是原生 <dialog>:它通过 z-index 管理器叠放,所以在里面打开的 Select、Popover、Tooltip 会显示在它上面,按 Esc 先关最里层。打开期间焦点留在里面,背后的页面对读屏软件隐藏、也不能滚动;关闭后焦点回到打开它的元素。

演示

基础用法

用 show 和 onUpdateShow 控制。打开时焦点落在正文的第一个输入框;按 Esc、点遮罩、点 ×、取消和保存都会关闭。

异步确认和阻止关闭

onPositiveClick 返回 Promise 时,按钮会显示加载,直到它结束。返回 false(或 resolve 成 false 的 Promise)则不关闭;onClose 对 × 也一样。

必须做出选择

maskClosable={false}、closeOnEsc={false} 和 closable={false} 之后只能点按钮关闭。onMaskClick 和 onEsc 仍会报告这些尝试。

长内容

标题和按钮固定不动,正文在两者之间滚动。footer 在按钮上方加一行。

对话框和底部面板

presentation="auto"(默认)在宽屏是对话框,窗口窄于 640px(Grid 的 s 断点)时变成底部面板;dialog 和 sheet 固定其中一种。底部面板占满屏宽、从下方滑入、避开 iPhone 底部的横条,按钮等宽排开。整个应用的默认值可以用 ConfigProvider 的 componentOptions={{ Modal: { presentation: "dialog" } }} 设置。

自定义外观

raw 去掉背景、标题行和 ×,只保留遮罩、位置、动画和焦点管理。请用 aria-label 或 aria-labelledby 给对话框起名。

内部的浮层

模态框里的 Select 会显示在它上面;从模态框里再打开一个模态框会叠在最上层,按 Esc 或点它的遮罩只关闭最上面那个。

Props

名称类型默认值说明版本
showbooleanundefined受控的显示状态。未发布
defaultShowbooleanfalse非受控时的初始显示状态。未发布
onUpdateShow(show: boolean) => voidundefined模态框要打开或关闭时,以新的显示状态调用。未发布
titleReactNodeundefined标题,同时作为对话框的名称。未发布
childrenReactNodeundefined正文。纯文本时也作为对话框的描述(aria-describedby)。未发布
footerReactNodeundefined正文下方、按钮上方的一行。未发布
actionReactNodeundefined替换确认 / 取消按钮。未发布
positiveTextReactNodeundefined主按钮文字;设置了才显示。未发布
negativeTextReactNodeundefined次按钮文字;设置了才显示。未发布
positiveButtonPropsPartial<ButtonProps>undefined主按钮的额外属性,比如 type: "error"。未发布
negativeButtonPropsPartial<ButtonProps>undefined次按钮的额外属性。未发布
onPositiveClick(event: MouseEvent) => boolean | void | Promise<boolean | void>undefined点主按钮时调用。返回 false 不关闭;返回 Promise 时显示加载。未发布
onNegativeClick(event: MouseEvent) => boolean | void | Promise<boolean | void>undefined点次按钮时调用。返回 false 不关闭。未发布
closablebooleantrue是否显示 × 按钮。未发布
onClose() => boolean | void | Promise<boolean | void>undefined点 × 时调用。返回 false 不关闭。未发布
rawbooleanfalse去掉背景、标题行和 ×,自己画外观。未发布
presentation'dialog' | 'sheet' | 'auto''auto'对话框、底部面板,或窄于 640px 时变成底部面板的对话框。未发布
maskClosablebooleantrue点遮罩是否关闭。未发布
onMaskClick(event: MouseEvent) => voidundefined点遮罩时调用,不论是否关闭。未发布
closeOnEscbooleantrue按 Esc 是否关闭。未发布
onEsc() => voidundefined按 Esc 时调用,不论是否关闭。未发布
autoFocusbooleantrue打开时聚焦正文里第一个可聚焦元素(其次是按钮,最后是 ×);关闭此项则聚焦对话框本身。未发布
trapFocusbooleantrue把 Tab 限制在里面,并对读屏软件隐藏页面(aria-modal)。未发布
blockScrollbooleantrue打开期间禁止页面滚动。未发布
displayDirective'if' | 'show''if'关闭后卸载,还是保留 DOM 并隐藏。未发布
transformOrigin'mouse' | 'center''mouse'从打开它的那次点击处展开,还是从自身中心展开。未发布
tostring | HTMLElement | falseundefined挂载位置;false 表示就地渲染。默认是 ConfigProvider 的 portalContainer,其次是 document.body。未发布
zIndexnumberundefined固定的 z-index,不再按打开顺序叠在之前的浮层上面。未发布
onAfterEnter() => voidundefined进入动画结束时调用。未发布
onAfterLeave() => voidundefined离开动画结束时调用。未发布

其余属性以及 className、style、ref 都传给对话框元素(role="dialog");宽度用 style 设置,底部面板仍会撑满屏宽。开启「减少动态效果」时,对话框和底部面板只做淡入淡出。