跳转到内容

Modal 模态框

模态框组件可以用来快速创建对话框、弹出窗口,灯箱等任何你所需的组件。

组件会在背景组件前渲染其children节点。 The Modal offers important features:

  • 💄 Manages modal stacking when one-at-a-time just isn't enough.
  • 🔐 Creates a backdrop, for disabling interaction below the modal.
  • 🔐 It disables scrolling of the page content while open.
  • ♿️它妥善管理焦点;移动到模态内容, 并保持它直到模态关闭。
  • ♿️自动添加适当的ARIA角色。
  • 📦 5kB 已压缩的包

术语注释。 “模态框”(Modal)这个词有时也被用来指代“对话框”,但是这种用法属于误用。 A modal window describes parts of a UI. 如果一个元素阻挡了用户与应用的其它部分的互动,这个元素就是模态的。

当你创建一个模态对话框时,使用对话框(Dialog)组件比直接使用模态框更佳。 以下的组件将将模态框作为一个低级别的组件运用:

简单的模态

<button type="button" onClick={handleOpen}>
  Open Modal
</button>
<Modal
  open={open}
  onClose={handleClose}
  aria-labelledby="simple-modal-title"
  aria-describedby="simple-modal-description"
>
  {body}
</Modal>

Notice that you can disable the outline (often blue or gold) with the outline: 0 CSS property.

过渡动画

The open/close state of the modal can be animated with a transition component. This component should respect the following conditions:

  • Be a direct child descendent of the modal.
  • Have an in prop. This corresponds to the open / close state.
  • Call the onEnter callback prop when the enter transition starts.
  • Call the onExited callback prop when the exit transition is completed. These two callbacks allow the modal to unmount the child content when closed and fully transitioned.

Modal has built-in support for react-transition-group.

Alternatively, you can use react-spring.

Server-side modal

React doesn't support the createPortal() API on the server. In order to display the modal, you need to disable the portal feature with the disablePortal prop:

<Modal
  disablePortal
  disableEnforceFocus
  disableAutoFocus
  open
  aria-labelledby="server-modal-title"
  aria-describedby="server-modal-description"
  className={classes.modal}
  container={() => rootRef.current}
>
  <div className={classes.paper}>
    <h2 id="server-modal-title">Server-side modal</h2>
    <p id="server-modal-description">If you disable JavaScript, you will still see me.</p>
  </div>
</Modal>

局限性

Focus trap

The modal moves the focus back to the body of the component if the focus tries to escape it.

This is done for accessibility purposes, however, it might create issues. In the event the users need to interact with another part of the page, e.g. with a chatbot window, you can disable the behavior:

<Modal disableEnforceFocus />

可访问性

(WAI-ARIA: https://www.w3.org/TR/wai-aria-practices/#dialog_modal)

  • 记得用 aria-labelledby="id..." 属性来指向Modal 的标题. Additionally, you may give a description of your modal with the aria-describedby="id..." prop on the Modal.

      <Modal
      aria-labelledby="modal-title"
      aria-describedby="modal-description"
      >
      <h2 id="modal-title">
        My Title
      </h2>
      <p id="modal-description">
        My Description
      </p>
      </Modal>
  • The WAI-ARIA authoring practices can help you set the initial focus on the most relevant element, based on your modal content.

  • A modal window overlys on either the primary window or another modal window. Windows under a modal are inert. That is, users cannot interact with content outside an active modal window.