Modal
A modal appears over the original content and interrupts the user's workflow to present critical information or request the user to take action.
#Examples
#Default
In most cases, a Modal
should always be dismissible and initiated by the user. This gives the user the freedom and control to decide when they want to see that modal. In certain cases, a system-initiated Modal
is required to prevent or correct critical errors. Use a system-initiated Modal
sparingly as it interrupts the user's current task. The user may be surprised by the unexpected behavior of a system-initiated Modal
.
The example serves as a base Modal
used for information-only content and does not prompt the user for an action. A Modal
consists of a header, a close button, and body content.
- Header: includes the modal title (with an optional tooltip) and an optional icon.
- Body content: provides information and/or controls necessary to complete the modal's task.
- Close button: use the close button to close the modal without submitting any data.
- Overlay: screen overlay, also referred to as
backdrop
, hides the page's content.
const [showModal, setShowModal] = useState(false);
return (
<>
<Button aria-haspopup="dialog" onClick={() => setShowModal(true)}>
Trigger modal
</Button>
<Modal shown={showModal} headerTitle="Default modal" onClose={() => setShowModal(false)}>
<Modal.Content>
<Paragraph>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nemo repellendus
obcaecati praesentium illo, voluptate fugiat quisquam vitae nostrum modi earum eos
nesciunt at, placeat sint vel quas quae aliquid.
</Paragraph>
</Modal.Content>
</Modal>
</>
);
#Footer
Modals can optionally contain a footer. This section is intended for information and actions that relate to the Modal
as a whole. In most cases, that will be the Action Bar component, which required the user to complete or cancel the modal task.
Add a footer by placing a Modal.Footer
component inside a Modal
as its last child.
In most cases,
- use two buttons to give the user a clear choice.
- avoid using more than three buttons.
- a destructive button can replace a primary button in the footer to confirm actions that will cause significant data loss if clicked accidentally.
const [showModal, setShowModal] = useState(false);
return (
<>
<Button aria-haspopup="dialog" onClick={() => setShowModal(true)}>
Trigger modal
</Button>
<Modal shown={showModal} headerTitle="Modal with footer" onClose={() => setShowModal(false)}>
<Modal.Content>
<Paragraph>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nemo repellendus
obcaecati praesentium illo, voluptate fugiat quisquam vitae nostrum modi earum eos
nesciunt at, placeat sint vel quas quae aliquid.
</Paragraph>
</Modal.Content>
<Modal.Footer>
<ActionBar
primary={{ children: "Confirm", onClick: () => setShowModal(false) }}
cancel={{ children: "Cancel", onClick: () => setShowModal(false) }}
/>
</Modal.Footer>
</Modal>
</>
);
#Sizes
Choose a size that works best for the amount of modal content you have. For short messages, use a small
size of a Modal
to maintain user focus. When using medium
and fullWidth
Modal
, use them sparingly with consideration for readability.
Use the size
property to adjust the width of the Modal
. These are the available sizes and their intended use cases:
small
is the default value and is intended to be used for single-column layouts.medium
is intended to be used for multiple-column layouts.fullWidth
is intended to present images or present a layout with columns.
Here's an example of a medium
sized Modal
.
const [showModal, setShowModal] = useState(false);
return (
<>
<Button aria-haspopup="dialog" onClick={() => setShowModal(true)}>
Trigger modal
</Button>
<Modal
shown={showModal}
size="medium"
headerTitle="Medium sized modal"
onClose={() => setShowModal(false)}
>
<Modal.Content>
<Paragraph>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nemo repellendus
obcaecati praesentium illo, voluptate fugiat quisquam vitae nostrum modi earum eos
nesciunt at, placeat sint vel quas quae aliquid.
</Paragraph>
</Modal.Content>
</Modal>
</>
);
Max heights
Each Modal
size
has a max height to maintain a proper window ratio. Consider sizing up the modal if vertical scrolling is too much of a problem due to a max height. See the scrolling behavior below. It may be necessary to use a full page instead of a fullWidth
modal if the height of the fullWidth
modal is still not sufficient. Especially if the content contains a lot of data and it takes a while to load.
Here's an example of a fullWidth
Modal
.
const [showModal, setShowModal] = useState(false);
return (
<>
<Button aria-haspopup="dialog" onClick={() => setShowModal(true)}>
Trigger modal
</Button>
<Modal
shown={showModal}
size="fullWidth"
headerTitle="Full width modal"
onClose={() => setShowModal(false)}
>
<Modal.Content>
<Paragraph>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nemo repellendus
obcaecati praesentium illo, voluptate fugiat quisquam vitae nostrum modi earum eos
nesciunt at, placeat sint vel quas quae aliquid.
</Paragraph>
</Modal.Content>
</Modal>
</>
);
#Padding
The Modal.Content
component provides the same padding
options as the Content component:
large
medium
(default value)small
none
compact
The example shows a Modal.Content
with the padding
property set to large
.
const [showModal, setShowModal] = useState(false);
return (
<>
<Button aria-haspopup="dialog" onClick={() => setShowModal(true)}>
Trigger modal
</Button>
<Modal
shown={showModal}
headerTitle="Modal with large padding"
onClose={() => setShowModal(false)}
>
<Modal.Content padding="large">
<Paragraph>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nemo repellendus
obcaecati praesentium illo, voluptate fugiat quisquam vitae nostrum modi earum eos
nesciunt at, placeat sint vel quas quae aliquid.
</Paragraph>
</Modal.Content>
</Modal>
</>
);
#Tooltip in header
Adding a tooltip to the header is not recommended. The header should be clear and inform the user about the purpose of the modal.
A header should only contain a tooltip if we need to:
- introduce an unfamiliar term;
- reassure the user to perform the required actions.
A tooltip in the header should not prompt the user to take any additional action.
To add a tooltip to the header you must use the headerTitleTooltipText
prop to ensure proper accessibility. Do not add the Tooltip component to the headerTitle
prop.
If you need to change the placement of the tooltip you can use the headerTitleTooltipPlacement
prop.
const [showModal, setShowModal] = useState(false);
return (
<>
<Button aria-haspopup="dialog" onClick={() => setShowModal(true)}>
Trigger modal
</Button>
<Modal
shown={showModal}
headerTitle="Header title with tooltip"
headerTitleTooltipText="Lorem ipsum dolor sit amet consectetur adipisicing elit."
headerTitleTooltipPlacement="bottom"
onClose={() => setShowModal(false)}
>
<Modal.Content>
<Paragraph>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nemo repellendus
obcaecati praesentium illo, voluptate fugiat quisquam vitae nostrum modi earum eos
nesciunt at, placeat sint vel quas quae aliquid.
</Paragraph>
</Modal.Content>
</Modal>
</>
);
#Icon in header
Use a header with an information icon to remind the user of the importance of taking a specific action. Use a consistent color and purpose for each type of information icon, as described in the Message component.
const [showModal, setShowModal] = useState(false);
return (
<>
<Button aria-haspopup="dialog" onClick={() => setShowModal(true)}>
Trigger modal
</Button>
<Modal
headerIcon={<IconPotentialIssue />}
headerTitle="Header title with icon"
shown={showModal}
onClose={() => setShowModal(false)}
>
<Modal.Content>
<Paragraph>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nemo repellendus
obcaecati praesentium illo, voluptate fugiat quisquam vitae nostrum modi earum eos
nesciunt at, placeat sint vel quas quae aliquid.
</Paragraph>
</Modal.Content>
</Modal>
</>
);
#No close button in header
Be careful when using this variant. If the close button is not provided, the user is forced to understand the content and make a decision about which button to choose to continue the workflow.
This variant is recommended to use only when
- the system requires the user to acknowledge the presented information.
- the user’s actions may destroy data or cause significant changes. This allows the user to confirm the actions.
const [showModal, setShowModal] = useState(false);
return (
<>
<Button aria-haspopup="dialog" onClick={() => setShowModal(true)}>
Trigger modal
</Button>
<Modal
headerTitle="Header without close button"
shown={showModal}
onClose={() => setShowModal(false)}
hideClose
>
<Modal.Content>
<Paragraph>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nemo repellendus
obcaecati praesentium illo, voluptate fugiat quisquam vitae nostrum modi earum eos
nesciunt at, placeat sint vel quas quae aliquid.
</Paragraph>
</Modal.Content>
<Modal.Footer>
<ActionBar
primary={{ children: "Confirm", onClick: () => setShowModal(false) }}
cancel={{ children: "Cancel", onClick: () => setShowModal(false) }}
/>
</Modal.Footer>
</Modal>
</>
);
#Dropzone
DialogDropzone
is not a feature for end users. It is a structural component that allows developers to control where the Dialog
component will appear in the Document Object Model (DOM).
By default, modals are appended to the DOM in the bottom of the body
element. The DialogDropzone
component lets you control where in the DOM the Modal
is rendered, allowing it to inherit styles, if you don't use a global stylesheet.
<DialogDropzone />
#Properties
Property | Description | Defined | Value |
---|---|---|---|
shownRequired | boolean | ||
onCloseRequired | function | ||
childrenOptional | element | ||
onUnmountOptional | function | ||
sizeOptional | "fullWidth" | "medium" | "small" | ||
hideHeaderOptional | unknown | ||
aria-labelledbyOptional | string | ||
headerTitleOptional | element | ||
classNameOptional | string Custom className that's applied to the outermost element (only intended for special cases) | ||
styleOptional | object Style object to apply custom inline styles (only intended for special cases) | ||
idOptional | string | ||
headerTitleTooltipTextOptional | | string | number | element | ||
headerTitleTooltipPlacementOptional | "bottom" | "bottom-end" | "bottom-start" | "left" | "left-end" | "left-start" | "right" | "right-end" | "right-start" | "top" | "top-end" | "top-start" | ||
headerIconOptional | element | ||
hideCloseOptional | boolean | ||
data-observe-keyOptional | string Unique string, used by external script e.g. for event tracking |
#Guidelines
#Best practices
#Do not use when
#Accessibility
Explore detailed guidelines for this component: Accessibility Specifications