Skip to contentSkip to navigationSkip to topbar
Figma
Star

Modal

Version 16.1.1GithubStorybook

A Modal is a page overlay that displays information and blocks interaction with the page until an action is taken or the Modal is dismissed.

Component preview theme
const ModalTrigger = () => {
// Modal properties
const [isOpen, setIsOpen] = React.useState(false);
const handleOpen = () => setIsOpen(true);
const handleClose = () => setIsOpen(false);
const modalHeadingID = useUID();
return (
<div>
<Button variant="primary" onClick={handleOpen}>
Open modal
</Button>
<Modal ariaLabelledby={modalHeadingID} isOpen={isOpen} onDismiss={handleClose} size="default">
<ModalHeader>
<ModalHeading as="h3" id={modalHeadingID}>
Choose an author
</ModalHeading>
</ModalHeader>
<ModalBody>
<Paragraph>
“If there’s a book that you want to read, but it hasn’t been written yet, then you must write it.”
— Toni Morrison
</Paragraph>
<Label htmlFor="author">Choose an author</Label>
<Select id="author">
<Option value="baldwin">James Baldwin</Option>
<Option value="brown">adrienne maree brown</Option>
<Option value="butler">Octavia Butler</Option>
<Option value="coates">Ta-Nehisi Coates</Option>
<Option value="lorde">Audre Lorde</Option>
<Option value="nnedi">Nnedi Okorafor</Option>
</Select>
</ModalBody>
<ModalFooter>
<ModalFooterActions>
<Button variant="secondary" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary">Done</Button>
</ModalFooterActions>
</ModalFooter>
</Modal>
</div>
);
};
render(
<ModalTrigger />
)

Guidelines

Guidelines page anchor

About Modals

About Modals page anchor

A Modal is a dialog that appears over the main content and moves the system into a special mode requiring user interaction. Modals are typically used to focus a user's attention for any of these scenarios:

  • When you want to capture information from the user without having them leave the parent page.
  • When you want to show additional information to the user without losing context of the parent page.

If you need to to guarantee a user acknowledges a critical piece of information, use an Alert Dialog instead.

Users cannot interact with content outside an active modal window until the user explicitly closes it. When the modal opens, focus moves to an element contained in it (by default, the first element that can be focused) in the modal, and the focus should stay in and cycle through the modal's content. Focus shouldn't return to the underlying page until the user closes the modal. This can happen in any of the following ways:

  • Presses the Esc key
  • Presses the close "x" button in the Modal header
  • Presses a "Cancel" button in the Modal footer
  • Clicks outside of the Modal
  • Performs another action that closes the Modal

You can compose a Modal content area to support your use case, but elements such as Paragraph and Form Input are commonly used. See examples for common Modal patterns and dos/don'ts.

  • All elements required to interact with the modal, including closing or acknowledging it, are contained in the modal since they trap focus, and users can't interact with the underlying page.
  • Tabbing through a Modal will cycle through its content in the same way it does on a page. A Modal also supports pressing the Escape key to close the Modal.
  • The element that serves as the modal container has a role of dialog.
  • The modal must be labelled. It can be labelled either by:
    • Setting a value for the aria-labelledby property that refers to a visible ModalHeading.
    • Providing a label directly specifing by aria-label attribute on the Modal container.

A modal is composed of:

  • Header — Headers include a Heading and close button. Heading text should be concise (2-4 words and no more than one line) and describe the information or action the modal is presenting.
  • Body — This container has no content requirements and allows you to compose a Modal as you need. Common components you might use include supporting body copy (with Paragraph) and form elements.
  • Footer — This contains all possible modal actions aligned to the right side of the modal (by default) to show users they're progressing through their task, whether that's on the parent page, on a new page, or in another step in the modal.
(information)

Provide an accessible label

Be sure to assign the aria-labelledby property on the modal container to the id of the modal heading.

A Modal has a default width of 608 px to allow for an optimal reading length at 70-75 characters per line at default Paragraph size at 100% magnification. At viewports smaller than 608 px, the Modal will fill the width of the viewport and pin to the bottom. The Modal will grow in height with the amount of content in it. Once the modal reaches 90% of the height of the viewport, the body will begin to scroll.

Component preview theme
const ModalTrigger = () => {
// Modal properties
const [isOpen, setIsOpen] = React.useState(false);
const handleOpen = () => setIsOpen(true);
const handleClose = () => setIsOpen(false);
const modalHeadingID = useUID();
return (
<div>
<Button variant="primary" onClick={handleOpen}>
Open modal
</Button>
<Modal ariaLabelledby={modalHeadingID} isOpen={isOpen} onDismiss={handleClose} size="default">
<ModalHeader>
<ModalHeading as="h3" id={modalHeadingID}>
Choose an author
</ModalHeading>
</ModalHeader>
<ModalBody>
<Paragraph>
“If there’s a book that you want to read, but it hasn’t been written yet, then you must write it.”
— Toni Morrison
</Paragraph>
<Label htmlFor="author">Choose an author</Label>
<Select id="author">
<Option value="baldwin">James Baldwin</Option>
<Option value="brown">adrienne maree brown</Option>
<Option value="butler">Octavia Butler</Option>
<Option value="coates">Ta-Nehisi Coates</Option>
<Option value="lorde">Audre Lorde</Option>
<Option value="nnedi">Nnedi Okorafor</Option>
</Select>
</ModalBody>
<ModalFooter>
<ModalFooterActions>
<Button variant="secondary" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary">Done</Button>
</ModalFooterActions>
</ModalFooter>
</Modal>
</div>
);
};
render(
<ModalTrigger />
)

Use a wide modal (816px) when your content requires it. For example, you may need to place a two-column Grid layout or video player in a wide modal.

At viewports smaller than 816 px, the Modal will shift to the default width (608px). The wide Modal follows all other sizing behavior as the default Modal.

Component preview theme
const ModalTrigger = () => {
// Modal properties
const [isOpen, setIsOpen] = React.useState(false);
const handleOpen = () => setIsOpen(true);
const handleClose = () => setIsOpen(false);
const modalHeadingID = useUID();
// Content properties
const [documentName, setDocumentName] = React.useState('');
const [address1, setAddress1Name] = React.useState('');
const [address2, setAddress2Name] = React.useState('');
const documentNameInputID = useUID();
const address1InputID = useUID();
const address2InputID = useUID();
return (
<div>
<Button variant="primary" onClick={handleOpen}>
Add supporting document
</Button>
<Modal ariaLabelledby={modalHeadingID} isOpen={isOpen} onDismiss={handleClose} size="wide">
<ModalHeader>
<ModalHeading as="h3" id={modalHeadingID}>
Add supporting document
</ModalHeading>
</ModalHeader>
<ModalBody>
<Grid gutter="space50">
<Column>
<Box marginBottom="space50">
<Label htmlFor={documentNameInputID}>Supporting document name</Label>
<Input onChange={(e) => setDocumentName(e.currentTarget.value)} id={documentNameInputID} type="text" value={documentName} />
</Box>
<Box marginBottom="space50">
<Label htmlFor={address1InputID}>Address 1</Label>
<Input onChange={(e) => setAddress1Name(e.currentTarget.value)} id={address1InputID} type="text" value={address1} />
</Box>
<Box>
<Label htmlFor={address2InputID}>Address 2</Label>
<Input onChange={(e) => setAddress2Name(e.currentTarget.value)} id={address2InputID} type="text" value={address2} />
</Box>
</Column>
<Column>
<Box backgroundColor="colorBackground" height="size20" display="flex" alignItems="center" justifyContent="center">
<Text as="p" textAlign="center">Upload supporting document</Text>
</Box>
</Column>
</Grid>
</ModalBody>
<ModalFooter>
<ModalFooterActions>
<Button variant="secondary" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary">Add document</Button>
</ModalFooterActions>
</ModalFooter>
</Modal>
</div>
);
};
render(
<ModalTrigger />
)

When a Modal opens user focus is set inside the Modal. By default, user focus will be set on the first focusable element which is the close button. You can choose to explicitly set focus to any focusable UI control inside the modal.

To set a different initial focus target, set the initialFocusRef prop on the Modal container to a ref of a focusable element inside the Modal.

Component preview theme
const ModalTrigger = () => {
// Modal properties
const [isOpen, setIsOpen] = React.useState(false);
const handleOpen = () => setIsOpen(true);
const handleClose = () => setIsOpen(false);
const modalHeadingID = useUID();
// ref of target intial focus element
const nameInputRef = React.createRef();
// Content properties
const [name, setName] = React.useState('');
const inputID = useUID();
return (
<div>
<Button variant="primary" onClick={handleOpen}>
New project
</Button>
<Modal
ariaLabelledby={modalHeadingID}
isOpen={isOpen}
onDismiss={handleClose}
// set inital focus here
initialFocusRef={nameInputRef}
size="default"
>
<ModalHeader>
<ModalHeading as="h3" id={modalHeadingID}>
Create a new project
</ModalHeading>
</ModalHeader>
<ModalBody>
<Box as="form">
<Label htmlFor={inputID}>Project Name</Label>
<Input
id={inputID}
value={name}
// assign the target ref here
ref={nameInputRef}
onChange={e => setName(e.currentTarget.value)}
type="text"
/>
</Box>
</ModalBody>
<ModalFooter>
<ModalFooterActions>
<Button variant="secondary" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary">Submit</Button>
</ModalFooterActions>
</ModalFooter>
</Modal>
</div>
);
};
render(
<ModalTrigger />
)

To internationalize the modal, simply pass different text as children to the Modal components. The only exception is the dismiss button in the ModalHeader component–to change the button’s text, use the i18nDismissLabel prop.

Component preview theme
const ModalTrigger = () => {
// Modal properties
const [isOpen, setIsOpen] = React.useState(false);
const handleOpen = () => setIsOpen(true);
const handleClose = () => setIsOpen(false);
const modalHeadingID = useUID();
return (
<div>
<Button variant="primary" onClick={handleOpen}>
Abrir modal
</Button>
<Modal ariaLabelledby={modalHeadingID} isOpen={isOpen} onDismiss={handleClose} size="default">
<ModalHeader i18nDismissLabel='Cerrar modal'>
<ModalHeading as="h3" id={modalHeadingID}>
Escoja una autora
</ModalHeading>
</ModalHeader>
<ModalBody>
<Paragraph>
"Vivir en las fronteras y en los márgenes, mantener intacta la identidad múltiple y la integridad, es como tratar de nadar en un nuevo elemento, un elemento 'extranjero'"
— Gloria E. Anzaldúa
</Paragraph>
<Label htmlFor="author">Escoja una autora</Label>
<Select id="author">
<Option value="allende">Isabel Allende</Option>
<Option value="cisneros">Sandra Cisneros</Option>
<Option value="santiago">Esmeralda Santiago</Option>
<Option value="anzaldúa">Gloria E. Anzaldúa</Option>
</Select>
</ModalBody>
<ModalFooter>
<ModalFooterActions>
<Button variant="secondary" onClick={handleClose}>
Cancelar
</Button>
<Button variant="primary">Confirmar</Button>
</ModalFooterActions>
</ModalFooter>
</Modal>
</div>
);
};
render(
<ModalTrigger />
)

Include a header, body, and footer in your modal.

  • The header should be concise (2-4 words), start with a verb, and clearly describe the information or action the modal presents.
  • The body should expand on the topic in the header. If you need multiple sections of content with Headings in the body, use a Heading with the heading40 variant.
  • The footers should include 1–2 actions aligned to the right side of the modal. Place the primary action farthest on the right to indicate to users they're progressing through their task.
Footer actions alignment page anchor

By default the footer actions are aligned to the right of the modal using the Flexbox property justify-content. This should be the most common configuration you should choose.

Component preview theme
<ModalFooter>
<ModalFooterActions>
<Button variant="secondary">Cancel</Button>
<Button variant="primary">Save</Button>
</ModalFooterActions>
</ModalFooter>
Footer actions left alignment page anchor

Sometimes you may need to do left alignment of buttons. This is less common. To do so use the justify property on the ModalFooterActions component and set it to start.

Component preview theme
<ModalFooter>
<ModalFooterActions justify="start">
<Button variant="secondary">Cancel</Button>
<Button variant="primary">Save</Button>
</ModalFooterActions>
</ModalFooter>
Footer actions directional alignment page anchor

By using both alignment types, you are able to create directional alignments of footer actions.

Component preview theme
<ModalFooter>
<ModalFooterActions justify="start">
<Button variant="secondary">Back</Button>
</ModalFooterActions>
<ModalFooterActions>
<Button variant="secondary">Cancel</Button>
<Button variant="primary">Save</Button>
</ModalFooterActions>
</ModalFooter>

Use a Modal to:

  • Request the user enter information to continue the current process.
  • Guide the user through a complex workflow with a series of steps, while still maintaining context of the task that initiated the modal.

Do not use modals to show important warnings, since they can be dismissed without the user acknowledging the information. Instead, use an Alert Dialog.

Do not use modals to show error messages. Refer to the error state pattern for additional guidance on components.

Do

Use a clear and concise heading to describe the purpose of the Modal.

Don't

Don't go into unnecessary detail in the heading about the purpose of the Modal.

Do

Keep the main call to action in the footer. If you're asking the user to perform an action, use a primary action (primary button or destructive button). If you need only to give the user a way to close the Modal, use a secondary button or rely on the close 'x' button.

Don't

Don't put buttons that close the Modal, or confirm and submit content, in the body.

Do

Use at most one primary and one secondary action in a Modal. Make the secondary action a 'Cancel' button, especially when you want to give users an explicit choice to decline the primary action. This is especially useful when the primary action is a destructive action.

Don't

Don't put more than one primary action in the footer. Avoid using the secondary button for an action that isn't 'Close' or 'Cancel' since users will be used to pressing a secondary button that escapes the Modal. If you need to provide another action, add a third button to the footer, or consider showing it elsewhere.