ModalProvider
Notes
An accessible modal component manager. ModalProvider does not create any UI of its own; it is intended to work with the modal UI components in this library such as Overlay. ModalProvider will handle opening and closing your UI component and manages focus, close on Escape, mask animation, and key accessible attributes.
There are four main steps to leverage ModalProvider:
The main export, ModalProvider, should be wrapped around your entire React application as near to the application root as possible. ModalProvider leverages React Context to expose the openModal and closeModal methods to your entire app.
In your html, create a sibling div to your React app's root div. Set a unique id attribute on that div, and pass that id as the targetElementId prop of the ModalProvider created in step one. ModalProvider uses a React Portal, and this targetElementId tells the provider where to render your modals. Using a sibling div to the react app makes z-index handling much easier.
For accessibility, we want to mark the main React app hidden from screen readers when a modal is open. For this reason, pass the id of the element to which your React app is mounted as the appElementId prop of the ModalProvider.
In your application, wherever you need to launch a modal, import ModalContext from this component, and access it using the React.useContext hook. This will give you access to the openModal method; now you simply pass the component you want to render to openModal via its 'component' property. See example to the right.
Also check out our Overlay docs for an example using Overlays.
Props
- appElementId
string
String id attribute which is set on the root of your React application. Modal provider will mark this element as aria-hidden while any modal is open.
- children
any
The portion of the React application that will have access to the ModalProvider 'openModal' and 'closeModal' methods. Generally, the ModalProvider should be near the root of your React app.
- targetElementId
string
String id attribute on the element to which modals will be attached.
Example: Opening one or more modals
const MyDialog = () => (<DialogconfirmText="Got it"// eslint-disable-next-line no-consoleonConfirm={() => console.log("Define a callback with the onConfirm prop.")}><div className='mx-auto' style={{ maxWidth: '500px' }}><Heading tagName='h2' size='md' className='pb5 text-semibold'>Sample error dialog</Heading><p className="mb3">Add an 'onConfirm' prop to do something when the user clicks the confirm button.</p></div></Dialog>);const MyOverlay = ({ headingText }) => {const { closeModal, openModal } = React.useContext(ModalContext);return (<Overlayalignment="fullscreen"closeProps={{ariaLabel: 'Close'}}><ContentColumn size="md" className="py5"><Heading id="dialog-heading" tagName="h2" size="md" className="text-semibold pb4">{headingText}</Heading><p className="pb3">You can open another modal as needed, for example to provide an error dialog.</p><Button visualStyle="positive" onClick={() => openModal({ariaLabel: 'Sample error dialog',component: MyDialog,})}>Open a sample error dialog</Button><p className="py3">Attach the closeModal function to any button click handlers if you expect them to close the modal.</p><Button visualStyle="positive" onClick={() => closeModal()}>Close overlay</Button></ContentColumn></Overlay>);};const SampleApp = () => {const { openModal } = React.useContext(ModalContext);const openCustomModal = () => {openModal({ariaLabel: 'Sample custom overlay',component: MyOverlay,// If your component's props can't be determined until runtime, you can pass them in// when opening the overlay.componentProps: {headingText: 'Sample overlay',},});};return (<div className="p3"><p className="pb3">ModalProvider is intended to work with the modal UI components in this library (dialog, overlay, swipe deck, top sheet).</p><Button onClick={openCustomModal}>Open an overlay modal</Button></div>)}const ModalExample = () => (<ModalProvider appElementId="js-content" targetElementId="modal-target"><SampleApp /></ModalProvider>);render(<ModalExample />);
Example: Pass an id to be able to close by id
const ID = 'modalIdentifier';const CustomDialog = () => {const { closeModal } = React.useContext(ModalContext);return (<DialogconfirmText="Confirm"cancelText="Cancel"// eslint-disable-next-line no-consoleonConfirm={() => console.log("Define a callback here.")}><div><div className='mx-auto' style={{ maxWidth: '500px' }}><Heading id="dialog1" tagName='h2' size='md' className='pb5 text-semibold'>Dialogs can contain anything</Heading><Button onClick={() => closeModal(ID)}>Close modal by ID</Button></div></div></Dialog>);};const SampleApp = () => {const { openModal } = React.useContext(ModalContext);return (<div className="p3"><p className="pb3">For custom uses cases, you may need to be able to programmatically close a specific modal. If you pass an 'id' to your `openModal()` request, you can close that specific modal by id later.</p><Button onClick={() =>openModal({component: CustomDialog,id: ID,ariaLabelledBy: 'dialog1'})}>Open modal</Button></div>)}const ModalExample = () => (<ModalProvider appElementId="js-content" targetElementId="modal-target"><SampleApp /></ModalProvider>);render(<ModalExample />);