Modal
The modal component provides a solid foundation for creating dialogs, popovers, lightboxes, or whatever else.
The component renders its children
node in front of a backdrop component.
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.
- ♿️ It properly manages focus; moving to the modal content, and keeping it there until the modal is closed.
- ♿️ Adds the appropriate ARIA roles automatically.
- 📦 5 kB gzipped.
Terminology note. The term "modal" is sometimes used to mean "dialog", but this is a misnomer. A modal window describes parts of a UI. An element is considered modal if it blocks interaction with the rest of the application.
If you are creating a modal dialog, you probably want to use the Dialog component rather than directly using Modal. Modal is a lower-level construct that is leveraged by the following components:
Simple modal
<button type="button" onClick={handleOpen}>
Open Modal
</button>
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={open}
onClose={handleClose}
>
<div style={modalStyle} className={classes.paper}>
<h2 id="simple-modal-title">Text in a modal</h2>
<p id="simple-modal-description">
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</p>
<SimpleModal />
</div>
</Modal>
Notice that you can disable the outline (often blue or gold) with the outline: 0
CSS property.
Transitions
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:
Server-side modal
If you disable JavaScript, you will still see me.
<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>
Accessibility
(WAI-ARIA: https://www.w3.org/TR/wai-aria-practices/#dialog_modal)
Be sure to add
aria-labelledby="id..."
, referencing the modal title, to theModal
. Additionally, you may give a description of your modal with thearia-describedby="id..."
prop on theModal
.<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.