Skip Navigation
React Magma

Component API

Modal

View Design Guidelines

Basic Usage

The Modal component renders its children node in front of a backdrop component. It also disables scrolling of the page content while open, properly manages focus; moving to the modal content, and keeping it there until the modal is closed, and adds the appropriate ARIA roles automatically.

The modal will only render if the isOpen prop is set to true. For that reason, it is redundant to show the modal using the following anti-pattern: {flag && <Modal isOpen={flag} />. Instead, simply use <Modal isOpen={flag} />

Although not required, it is helpful to inform users (especially screen reader users) when a button or link will trigger a modal dialog. This can be done by supplementing the button label or link text with "(opens modal dialog)" using the VisuallyHidden component.

import React from 'react';
import { Button, Hyperlink, Modal, VisuallyHidden } from 'react-magma-dom';
export function Example() {
const [showModal, setShowModal] = React.useState(false);
const buttonRef = React.useRef();
function handleOnClose() {
setShowModal(false);
buttonRef.current.focus();
}
return (
<>
<Modal header="Modal Title" onClose={handleOnClose} isOpen={showModal}>
<p>This is a modal, doing modal things.</p>
<p>
This is <Hyperlink to="#">linked text</Hyperlink> in the modal
</p>
<p>
<Button>This is a button</Button>
</p>
<p>
This is <Hyperlink to="#">some more linked text</Hyperlink> in the
modal
</p>
</Modal>
<Button onClick={() => setShowModal(true)} ref={buttonRef}>
Show Modal
<VisuallyHidden>(opens modal dialog)</VisuallyHidden>
</Button>
</>
);
}

Sizes

Sizes for modals include small, medium, and large, with medium being the default value.

import React from 'react';
import {
Button,
ButtonSize,
Modal,
ModalSize,
VisuallyHidden,
ButtonGroup,
} from 'react-magma-dom';
export function Example() {
const [showSmallModal, setShowSmallModal] = React.useState(false);
const [showLargeModal, setShowLargeModal] = React.useState(false);
const smallButtonRef = React.useRef();
const largeButtonRef = React.useRef();
return (
<>
<Modal
size={ModalSize.small}
header="Modal Small"
onClose={() => {
setShowSmallModal(false);
smallButtonRef.current.focus();
}}
isOpen={showSmallModal}
>
<p>This is a small modal, doing small modal things.</p>
</Modal>
<Modal
size={ModalSize.large}
header="Modal Large"
onClose={() => {
setShowLargeModal(false);
largeButtonRef.current.focus();
}}
isOpen={showLargeModal}
>
<p>This is a large modal, doing large modal things.</p>
</Modal>
<ButtonGroup>
<Button
size={ButtonSize.small}
onClick={() => setShowSmallModal(true)}
ref={smallButtonRef}
>
Show Small Modal
<VisuallyHidden>(opens modal dialog)</VisuallyHidden>
</Button>
<Button
size={ButtonSize.large}
onClick={() => setShowLargeModal(true)}
ref={largeButtonRef}
>
Show Large Modal
<VisuallyHidden>(opens modal dialog)</VisuallyHidden>
</Button>
</ButtonGroup>
</>
);
}

The modal header prop is optional. It can accept a node or a string, and will be rendered inside an H1. If there is a header passed in, the focus will be placed on the header when the modal opens. If not, the focus will be placed on the first actionable element.

import React from 'react';
import {
Button,
Modal,
ModalSize,
VisuallyHidden,
ButtonGroup,
ButtonGroupAlignment,
} from 'react-magma-dom';
export function Example() {
const [showModal, setShowModal] = React.useState(false);
const [showModalHeader, setShowModalHeader] = React.useState(false);
const buttonRef = React.useRef();
const headerButtonRef = React.useRef();
return (
<>
<Modal
size={ModalSize.small}
onClose={() => {
setShowModal(false);
buttonRef.current.focus();
}}
isOpen={showModal}
>
<p>This modal has no header.</p>
<ButtonGroup alignment={ButtonGroupAlignment.center}>
<Button onClick={() => setShowModal(false)}>OK</Button>
</ButtonGroup>
</Modal>
<Modal
header="This modal has a header"
size={ModalSize.small}
onClose={() => {
setShowModalHeader(false);
headerButtonRef.current.focus();
}}
isOpen={showModalHeader}
>
<p>This modal has no header.</p>
<ButtonGroup alignment={ButtonGroupAlignment.center}>
<Button onClick={() => setShowModalHeader(false)}>OK</Button>
</ButtonGroup>
</Modal>
<ButtonGroup>
<Button onClick={() => setShowModal(true)} ref={buttonRef}>
Show Modal with no header
<VisuallyHidden>(opens modal dialog)</VisuallyHidden>
</Button>
<Button onClick={() => setShowModalHeader(true)} ref={headerButtonRef}>
Show Modal with header
<VisuallyHidden>(opens modal dialog)</VisuallyHidden>
</Button>
</ButtonGroup>
</>
);
}

Hide Close Button

The close button can be hidden by using the isCloseButtonHidden prop. If this prop is used, it is mandatory to provide another way to close the modal.

import React from 'react';
import { Button, Modal } from 'react-magma-dom';
export function Example() {
const [showModal, setShowModal] = React.useState(false);
const buttonRef = React.useRef();
return (
<>
<Modal
header="Modal Title"
isCloseButtonHidden
onClose={() => {
setShowModal(false);
buttonRef.current.focus();
}}
isOpen={showModal}
>
<p>The standard modal close button is hidden.</p>
<Button onClick={() => setShowModal(false)}>Close this Dialog</Button>
</Modal>
<Button onClick={() => setShowModal(true)} ref={buttonRef}>
Show Modal
</Button>
</>
);
}

Custom Close Button

If you would like to add a custom close button to the Modal be sure not to use the same onClose function as it will mean that the function will be called twice (once internally and once by react-magma).

import React from 'react';
import { Button, Modal, VisuallyHidden } from 'react-magma-dom';
export function Example() {
const [showModal, setShowModal] = React.useState(false);
const [magmaCloseCalledTimes, setMagmaCloseCalledTimes] = React.useState(0);
const [internalCloseCalledTimes, setInternalCloseCalledTimes] =
React.useState(0);
const buttonRef = React.useRef();
function closeModal() {
setMagmaCloseCalledTimes(magmaCloseCalledTimes + 1);
setShowModal(false);
buttonRef.current.focus();
}
function customCloseModal() {
setInternalCloseCalledTimes(internalCloseCalledTimes + 1);
setShowModal(false);
buttonRef.current.focus();
}
return (
<>
<Modal header="Modal Title" onClose={closeModal} isOpen={showModal}>
Lorem ipsum dolar sit amet
<Button onClick={customCloseModal}>Close Modal</Button>
</Modal>
<p>
<strong>Magma Close Called Times:</strong> {magmaCloseCalledTimes}
</p>
<p>
<strong>Internal Close Called Times:</strong> {internalCloseCalledTimes}
</p>
<Button onClick={() => setShowModal(true)} ref={buttonRef}>
Show Modal <VisuallyHidden>(opens modal dialog)</VisuallyHidden>
</Button>
</>
);
}

isInverse

import React from 'react';
import {
Button,
Hyperlink,
Modal,
VisuallyHidden,
Card,
CardBody,
} from 'react-magma-dom';
export function Example() {
const [showModal, setShowModal] = React.useState(false);
const buttonRef = React.useRef();
return (
<>
<Modal
header="Modal Title"
onClose={() => {
setShowModal(false);
buttonRef.current.focus();
}}
isOpen={showModal}
isInverse
>
<p>This is a modal, doing modal things.</p>
<p>
This is{' '}
<Hyperlink to="#" isInverse>
linked text
</Hyperlink>{' '}
in the modal
</p>
<p>
<Button isInverse>This is a button</Button>
</p>
<p>
This is{' '}
<Hyperlink to="#" isInverse>
some more linked text
</Hyperlink>{' '}
in the modal
</p>
</Modal>
<Card isInverse>
<CardBody>
<Button onClick={() => setShowModal(true)} ref={buttonRef} isInverse>
Show Modal
<VisuallyHidden>(opens modal dialog)</VisuallyHidden>
</Button>
</CardBody>
</Card>
</>
);
}

This component uses forwardRef. The ref is applied to the div element that wraps the Modal content.

All of the global HTML attributes can be provided as props and will be applied to the div element that wraps the modal content.

= required prop

PropertyTypeDefaultDescription
children
Required
ReactNode | undefined
-The content of the component
closeAriaLabelstring
"Close dialog"The text read by screen readers for the close button
closeButtonSizefunction
-Style for the modal container
containerStyleCSSProperties
-Style for the modal container
headerReact.ReactNode
-The content of the modal header
isBackgroundClickDisabledboolean
falseIf true, clicking the backdrop will not dismiss the modal
isCloseButtonHiddenboolean
falseIf true, the close button the the modal will be suppressed
isEscKeyDownDisabledboolean
-If true, pressing the Escape key will not dismiss the modal
isInverseboolean
falseIf true, the component will have inverse styling to better appear on a dark background
isOpenboolean
falseIf true, the modal will be visible
onClosefunction
-Action that fires when the close button is clicked
onEscKeyDownfunction
-Action that fires when the Escape key is pressed
sizeenum, one of:
ModalSize.large
ModalSize.medium
ModalSize.small
ModalSize.mediumThe relative size of the modal
unmountOnExitboolean
trueIf true, the modal will removed from the DOM when closed
Deploys by Netlify