<Modal>
Creates a modal dialog.
This follows the pattern in ARIA Authoring Practices guidelines
This is a <Dialog>
wrapped in an element to mask the rest of the page. Additional code ensures the focus is contained within the modal.
Multiple modals can be opened, but only the top-most modal is active.
While a modal is open the rest of the document is inert. The inert polyfill is used to set the content to inert.
Modals use React portal to place them at the end of the document. This ensures local positioning does not interfere with the modal positioning and that the reset of the document can be set to inert.
Usage
const [open, setOpen] = useState(false);
<button
type="button"
aria-haspopup="dialog"
aria-expanded={open}
onClick={() => setOpen(!open)}
>
Show
</button>
{open && (
<Modal title="Title" onClose={() => setOpen(false)}>
<p>
Modal contents
</p>
</Dialog>
)}
Props
The props are mostly the same as a <Dialog>
.
Prop | Type | Default | Purpose |
---|---|---|---|
actions | Node | Add additional content before the close button | |
active | Boolean | true | If set to false, the dialog is considered not active and will not close on Escape |
arrow | Node | Adds content above the header. Intended for an error when positioning. | |
bodyClassName | String | "react-dialogs-active-modal" | This class is added to the <body> when the modal is active |
children | Node | Dialog contents | |
className | String | null | Class name of dialog |
classPrefix | String | "react-dialogs-modal" | Class prefix for BEM classes |
focus | Boolean | true | Set false to disable focusing the dialog when rendered |
id | String | Random value | The id of the dialog |
onClose | Function | Called when the dialog is closed. If omitted the close button will not be rendered and Esc will not close the dialog | |
title | Node | The dialog title |
Customisation
A number of props are provided to customise the appearance of the component.
The nameProps
props allow you to add your own attributes to each part, potentially overriding those already present. This is a good way to add your own classes.
The NameComponent
props allow you to replace or override each component. Pass a lower-case string to change the html element, or a full component if you want a more far reaching change. Bear-in-mind you will have to forwardRef
the DialogComponent
component.
<ModalComponent className={`${classPrefix} ${classPrefix}--active`} // <div>
<DialogComponent className={`${classPrefix}__dialog ${className}`} {...dialogProps}> // <div>
{arrow} // null
<HeaderComponent className={`${classPrefix}__header`} {...headerProps} /> // <div>
<TitleComponent className={`${classPrefix}__title`} {...titleProps} /> // <h2>
{actions} // null
<CloseButtonComponent className={`${classPrefix}__close-button`} {...closeButtonProps} /> // <button>
</HeaderComponent>
<BodyComponent className={`${classPrefix}__body`} {...bodyProps} /> // <div>
{children}
</BodyComponent>
</DialogComponent>
</ModalComponent>
Styling
A bodyClassName
is added to the body when a modal is active. This allows scrolling to be prevented while the modal is open.