Modal
Allow users to focus on critical information or an action by interrupting their workflow with an overlay
#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:
smallis the default value and is intended to be used for single-column layouts.mediumis intended to be used for multiple-column layouts.fullWidthis 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:
largemedium(default value)smallnonecompact
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 | stringCustom className that's applied to the outermost element (only intended for special cases) | ||
styleOptional | objectStyle 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 | stringUnique 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