Info alert:Beta feature
Examples
Basic modals
Basic modals give users the option to either confirm or cancel an action.
To flag an open modal, use the isOpen
property. To execute a callback when a modal is closed, use the onClose
property.
A modal must have a <ModalBody>
, containing the main content of the modal. The <ModalHeader>
and <ModalFooter>
components are not required, but are typically used to display the modal title and any button actions, respectively.
Scrollable modals
To enable keyboard-accessible scrolling of a modal’s content, pass tabIndex={0}
to the <ModalBody>
.
With a static description
To provide additional information about a modal, use the description
property. Descriptions are static and do not scroll with other modal content.
Top aligned
To override a modal's default center alignment, use the position
property. In this example, position
is set to "top", which moves the modal to the top of the screen.
Modal sizes
To adjust the size of a modal, use the variant
property. Modal variants include "small", "medium", "large", and "default".
In the following example, you can display each modal size option. To launch a modal with a specific size, first select the respective radio button, followed by the "Show modal" button.
Custom width
To choose a specific width for a modal, use the width
property. The following example has a width
of "50%".
Custom header
To add a custom header to a modal, your custom content must be passed as a child of the <ModalHeader>
component. Do not pass the title
property to <ModalHeader>
when using a custom header.
No header or footer
To exclusively present information in a modal, remove the header and/or footer.
When a modal has no header or footer, make sure to add an aria-label
explicitly stating this, so that those using assistive technologies can understand this context.
Title icon
To add an icon before a modal’s title, use the titleIconVariant
property, which can be set to a "success", "danger", "warning", or "info" variant. The following example uses a "warning" variant.
Custom title icon
To add a custom icon before a modal’s title, set titleIconVariant
to an imported custom icon. The following example imports and uses a bullhorn icon.
With wizard
To guide users through a series of steps in a modal, you can add a wizard to a modal. To configure the <Wizard>
, pass an array that contains a “name” and “component” value for each step into the steps
property.
With dropdown
To present a menu of actions or links to a user, you can add a dropdown to a modal.
To allow the dropdown to visually break out of the modal container, set the menuAppendTo
property to “parent”. Handle the modal’s closing behavior by listening to the onEscapePress
callback on the <Modal>
component. This allows the "escape" key to collapse the dropdown without closing the entire modal.
With help
To help simplify and explain complex models, add a help popover. Only place a help icon at the modal level if its information applies to all content in the modal. If the help popover is specific to a particular modal section, place the help icon beside that section instead.
With form
To collect user input within a modal, you can add a form.
To enable form submission from a button in the modal's footer (outside of the <Form>
), set the button's form
property equal to the form's id.
Custom focus
To customize which element inside the modal receives focus when initially opened, use the elementToFocus
property`.
Props
Modal
Name | Type | Default | Description |
---|---|---|---|
childrenrequired | React.ReactNode | Content rendered inside the modal. | |
appendTo | HTMLElement | (() => HTMLElement) | () => document.body | The parent container to append the modal to. Defaults to "document.body". |
aria-describedby | string | Id to use for the modal box description. This should match the ModalHeader labelId or descriptorId. | |
aria-label | string | Adds an accessible name to the modal when there is no title in the ModalHeader. | |
aria-labelledby | string | Id to use for the modal box label. This should include the ModalHeader labelId. | |
className | string | Additional classes added to the modal. | |
disableFocusTrap | boolean | Flag to disable focus trap. | |
elementToFocus | HTMLElement | SVGElement | string | The element to focus when the modal opens. By default the first focusable element will receive focus. | |
id | string | An id to use for the modal box container. | |
isOpen | boolean | false | Flag to show the modal. |
maxWidth | number | string | Maximum width of the modal. | |
onClose | (event: KeyboardEvent | React.MouseEvent) => void | Add callback for when the close button is clicked. This prop needs to be passed to render the close button | |
onEscapePress | (event: KeyboardEvent) => void | Modal handles pressing of the escape key and closes the modal. If you want to handle this yourself you can use this callback function. | |
ouiaId | number | string | Value to overwrite the randomly generated data-ouia-component-id. | |
ouiaSafe | boolean | true | Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. |
position | 'default' | 'top' | 'default' | Position of the modal. By default a modal will be positioned vertically and horizontally centered. |
positionOffset | string | Offset from alternate position. Can be any valid CSS length/percentage. | |
variant | 'small' | 'medium' | 'large' | 'default' | 'default' | Variant of the modal. |
width | number | string | Default width of the modal. |
ModalBody
Name | Type | Default | Description |
---|---|---|---|
aria-label | string | Accessible label applied to the modal body. This should be used to communicate important information about the modal body div element if needed, such as when it is scrollable. | |
children | React.ReactNode | Content rendered inside the modal body. | |
className | string | Additional classes added to the modal body. | |
role | string | Accessible role applied to the modal body. This will default to "region" if the aria-label property is passed in. Set to a more appropriate role as applicable based on the modal content and context. |
ModalHeader
Name | Type | Default | Description |
---|---|---|---|
children | React.ReactNode | Custom content rendered inside the modal header. If children are supplied then the tile, tileIconVariant and titleScreenReaderText props are ignored. | |
className | string | Additional classes added to the modal header. | |
description | React.ReactNode | Description of the modal. | |
descriptorId | string | Id of the modal description. | |
help | React.ReactNode | Optional help section for the modal header. | |
labelId | string | Id of the modal title. | |
title | React.ReactNode | Content rendered inside the modal title. | |
titleIconVariant | 'success' | 'danger' | 'warning' | 'info' | 'custom' | React.ComponentType<any> | Optional alert icon (or other) to show before the title. When the predefined alert types are used the default styling will be automatically applied. | |
titleScreenReaderText | string | Optional title label text for screen readers. |
ModalFooter
Name | Type | Default | Description |
---|---|---|---|
children | React.ReactNode | Content rendered inside the modal footer. | |
className | string | Additional classes added to the modal footer. |
CSS variables
Expand or collapse column | Selector | Variable | Value | |
---|---|---|---|---|
.pf-v5-c-modal-box | --pf-v5-c-modal-box--BackgroundColor | #fff | ||
--pf-v5-c-modal-box--BackgroundColor --pf-v5-global--BackgroundColor--100 $pf-v5-global--BackgroundColor--100 $pf-v5-color-white #fff | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--BoxShadow | 0 1rem 2rem 0 rgba(3, 3, 3, 0.16), 0 0 0.5rem 0 rgba(3, 3, 3, 0.1) | ||
--pf-v5-c-modal-box--BoxShadow --pf-v5-global--BoxShadow--xl $pf-v5-global--BoxShadow--xl 0 pf-size-prem(16px) pf-size-prem(32px) 0 rgba($pf-v5-color-black-1000, .16), 0 0 pf-size-prem(8px) 0 rgba($pf-v5-color-black-1000, .1) 0 pf-size-prem(16px) pf-size-prem(32px) 0 rgba(#030303, .16), 0 0 pf-size-prem(8px) 0 rgba(#030303, .1) 0 1rem 2rem 0 rgba(3, 3, 3, 0.16), 0 0 0.5rem 0 rgba(3, 3, 3, 0.1) | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--ZIndex | 500 | ||
--pf-v5-c-modal-box--ZIndex --pf-v5-global--ZIndex--xl $pf-v5-global--ZIndex--xl 500 | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--Width | 100% | ||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--MaxWidth | calc(100% - 2rem) | ||
--pf-v5-c-modal-box--MaxWidth calc(100% - --pf-v5-global--spacer--xl) calc(100% - $pf-v5-global--spacer--xl) calc(100% - pf-size-prem(32px)) calc(100% - 2rem) | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-sm--sm--MaxWidth | 35rem | ||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-md--Width | 52.5rem | ||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-lg--lg--MaxWidth | 70rem | ||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--MaxHeight | calc(100% - 3rem) | ||
--pf-v5-c-modal-box--MaxHeight calc(100% - --pf-v5-global--spacer--2xl) calc(100% - $pf-v5-global--spacer--2xl) calc(100% - pf-size-prem(48px)) calc(100% - 3rem) | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-align-top--spacer | 0.5rem | ||
--pf-v5-c-modal-box--m-align-top--spacer --pf-v5-global--spacer--sm $pf-v5-global--spacer--sm pf-size-prem(8px) 0.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-align-top--xl--spacer | 2rem | ||
--pf-v5-c-modal-box--m-align-top--xl--spacer --pf-v5-global--spacer--xl $pf-v5-global--spacer--xl pf-size-prem(32px) 2rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-align-top--MarginTop | 0.5rem | ||
--pf-v5-c-modal-box--m-align-top--MarginTop --pf-v5-c-modal-box--m-align-top--spacer --pf-v5-global--spacer--sm $pf-v5-global--spacer--sm pf-size-prem(8px) 0.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-align-top--MaxHeight | calc(100% - min(0.5rem, 3rem) - 0.5rem) | ||
--pf-v5-c-modal-box--m-align-top--MaxHeight calc(100% - min(--pf-v5-c-modal-box--m-align-top--spacer, --pf-v5-global--spacer--2xl) - --pf-v5-c-modal-box--m-align-top--spacer) calc(100% - min(--pf-v5-global--spacer--sm, $pf-v5-global--spacer--2xl) - --pf-v5-global--spacer--sm) calc(100% - min($pf-v5-global--spacer--sm, $pf-v5-global--spacer--2xl) - $pf-v5-global--spacer--sm) calc(100% - min(pf-size-prem(8px), pf-size-prem(48px)) - pf-size-prem(8px)) calc(100% - min(0.5rem, 3rem) - 0.5rem) | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-align-top--MaxWidth | calc(100% - min(0.5rem * 2, 2rem)) | ||
--pf-v5-c-modal-box--m-align-top--MaxWidth calc(100% - min(--pf-v5-c-modal-box--m-align-top--spacer * 2, --pf-v5-global--spacer--xl)) calc(100% - min(--pf-v5-global--spacer--sm * 2, $pf-v5-global--spacer--xl)) calc(100% - min($pf-v5-global--spacer--sm * 2, $pf-v5-global--spacer--xl)) calc(100% - min(pf-size-prem(8px) * 2, pf-size-prem(32px))) calc(100% - min(0.5rem * 2, 2rem)) | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-danger__title-icon--Color | #c9190b | ||
--pf-v5-c-modal-box--m-danger__title-icon--Color --pf-v5-global--danger-color--100 $pf-v5-global--danger-color--100 $pf-v5-color-red-100 #c9190b | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-warning__title-icon--Color | #f0ab00 | ||
--pf-v5-c-modal-box--m-warning__title-icon--Color --pf-v5-global--warning-color--100 $pf-v5-global--warning-color--100 $pf-v5-color-gold-400 #f0ab00 | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-success__title-icon--Color | #3e8635 | ||
--pf-v5-c-modal-box--m-success__title-icon--Color --pf-v5-global--success-color--100 $pf-v5-global--success-color--100 $pf-v5-color-green-500 #3e8635 | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-info__title-icon--Color | #2b9af3 | ||
--pf-v5-c-modal-box--m-info__title-icon--Color --pf-v5-global--info-color--100 $pf-v5-global--info-color--100 $pf-v5-color-blue-300 #2b9af3 | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box--m-custom__title-icon--Color | #009596 | ||
--pf-v5-c-modal-box--m-custom__title-icon--Color --pf-v5-global--custom-color--200 $pf-v5-global--custom-color--200 $pf-v5-color-cyan-300 #009596 | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__header--PaddingTop | 1.5rem | ||
--pf-v5-c-modal-box__header--PaddingTop --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__header--PaddingRight | 1.5rem | ||
--pf-v5-c-modal-box__header--PaddingRight --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__header--PaddingLeft | 1.5rem | ||
--pf-v5-c-modal-box__header--PaddingLeft --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__header--last-child--PaddingBottom | 1.5rem | ||
--pf-v5-c-modal-box__header--last-child--PaddingBottom --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__title--LineHeight | 1.3 | ||
--pf-v5-c-modal-box__title--LineHeight --pf-v5-global--LineHeight--sm $pf-v5-global--LineHeight--sm 1.3 | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__title--FontFamily | '"RedHatDisplay", helvetica, arial, sans-serif' | ||
--pf-v5-c-modal-box__title--FontFamily --pf-v5-global--FontFamily--heading $pf-v5-global--FontFamily--heading '"RedHatDisplay", helvetica, arial, sans-serif' | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__title--FontSize | 1.5rem | ||
--pf-v5-c-modal-box__title--FontSize --pf-v5-global--FontSize--2xl $pf-v5-global--FontSize--2xl pf-font-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__title-icon--MarginRight | 0.5rem | ||
--pf-v5-c-modal-box__title-icon--MarginRight --pf-v5-global--spacer--sm $pf-v5-global--spacer--sm pf-size-prem(8px) 0.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__title-icon--Color | #151515 | ||
--pf-v5-c-modal-box__title-icon--Color --pf-v5-global--Color--100 $pf-v5-global--Color--100 $pf-v5-color-black-900 #151515 | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__description--PaddingTop | 0.25rem | ||
--pf-v5-c-modal-box__description--PaddingTop --pf-v5-global--spacer--xs $pf-v5-global--spacer--xs pf-size-prem(4px) 0.25rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__body--MinHeight | calc(1rem * 1.5) | ||
--pf-v5-c-modal-box__body--MinHeight calc(--pf-v5-global--FontSize--md * --pf-v5-global--LineHeight--md) calc($pf-v5-global--FontSize--md * $pf-v5-global--LineHeight--md) calc(pf-font-prem(16px) * 1.5) calc(1rem * 1.5) | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__body--PaddingTop | 1.5rem | ||
--pf-v5-c-modal-box__body--PaddingTop --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__body--PaddingRight | 1.5rem | ||
--pf-v5-c-modal-box__body--PaddingRight --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__body--PaddingLeft | 1.5rem | ||
--pf-v5-c-modal-box__body--PaddingLeft --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__body--last-child--PaddingBottom | 1.5rem | ||
--pf-v5-c-modal-box__body--last-child--PaddingBottom --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__header--body--PaddingTop | 1rem | ||
--pf-v5-c-modal-box__header--body--PaddingTop --pf-v5-global--spacer--md $pf-v5-global--spacer--md pf-size-prem(16px) 1rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__close--Top | calc(1.5rem) | ||
--pf-v5-c-modal-box__close--Top calc(--pf-v5-global--spacer--lg) calc($pf-v5-global--spacer--lg) calc(pf-size-prem(24px)) calc(1.5rem) | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__close--Right | 1rem | ||
--pf-v5-c-modal-box__close--Right --pf-v5-global--spacer--md $pf-v5-global--spacer--md pf-size-prem(16px) 1rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__close--sibling--MarginRight | calc(2rem + 0.5rem) | ||
--pf-v5-c-modal-box__close--sibling--MarginRight calc(--pf-v5-global--spacer--xl + --pf-v5-global--spacer--sm) calc($pf-v5-global--spacer--xl + $pf-v5-global--spacer--sm) calc(pf-size-prem(32px) + pf-size-prem(8px)) calc(2rem + 0.5rem) | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__footer--PaddingTop | 1.5rem | ||
--pf-v5-c-modal-box__footer--PaddingTop --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__footer--PaddingRight | 1.5rem | ||
--pf-v5-c-modal-box__footer--PaddingRight --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__footer--PaddingBottom | 1.5rem | ||
--pf-v5-c-modal-box__footer--PaddingBottom --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__footer--PaddingLeft | 1.5rem | ||
--pf-v5-c-modal-box__footer--PaddingLeft --pf-v5-global--spacer--lg $pf-v5-global--spacer--lg pf-size-prem(24px) 1.5rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__footer--c-button--MarginRight | 1rem | ||
--pf-v5-c-modal-box__footer--c-button--MarginRight --pf-v5-global--spacer--md $pf-v5-global--spacer--md pf-size-prem(16px) 1rem | ||||
.pf-v5-c-modal-box | --pf-v5-c-modal-box__footer--c-button--sm--MarginRight | calc(1rem / 2) | ||
--pf-v5-c-modal-box__footer--c-button--sm--MarginRight calc(--pf-v5-c-modal-box__footer--c-button--MarginRight / 2) calc(--pf-v5-global--spacer--md / 2) calc($pf-v5-global--spacer--md / 2) calc(pf-size-prem(16px) / 2) calc(1rem / 2) | ||||
.pf-v5-c-modal-box.pf-m-sm | --pf-v5-c-modal-box--Width | 35rem | ||
--pf-v5-c-modal-box--Width --pf-v5-c-modal-box--m-sm--sm--MaxWidth 35rem | ||||
.pf-v5-c-modal-box.pf-m-md | --pf-v5-c-modal-box--Width | 52.5rem | ||
--pf-v5-c-modal-box--Width --pf-v5-c-modal-box--m-md--Width 52.5rem | ||||
.pf-v5-c-modal-box.pf-m-lg | --pf-v5-c-modal-box--Width | 70rem | ||
--pf-v5-c-modal-box--Width --pf-v5-c-modal-box--m-lg--lg--MaxWidth 70rem | ||||
.pf-v5-c-modal-box__title.pf-m-danger | --pf-v5-c-modal-box__title-icon--Color | #c9190b | ||
--pf-v5-c-modal-box__title-icon--Color --pf-v5-c-modal-box--m-danger__title-icon--Color --pf-v5-global--danger-color--100 $pf-v5-global--danger-color--100 $pf-v5-color-red-100 #c9190b | ||||
.pf-v5-c-modal-box__title.pf-m-warning | --pf-v5-c-modal-box__title-icon--Color | #f0ab00 | ||
--pf-v5-c-modal-box__title-icon--Color --pf-v5-c-modal-box--m-warning__title-icon--Color --pf-v5-global--warning-color--100 $pf-v5-global--warning-color--100 $pf-v5-color-gold-400 #f0ab00 | ||||
.pf-v5-c-modal-box__title.pf-m-success | --pf-v5-c-modal-box__title-icon--Color | #3e8635 | ||
--pf-v5-c-modal-box__title-icon--Color --pf-v5-c-modal-box--m-success__title-icon--Color --pf-v5-global--success-color--100 $pf-v5-global--success-color--100 $pf-v5-color-green-500 #3e8635 | ||||
.pf-v5-c-modal-box__title.pf-m-custom | --pf-v5-c-modal-box__title-icon--Color | #009596 | ||
--pf-v5-c-modal-box__title-icon--Color --pf-v5-c-modal-box--m-custom__title-icon--Color --pf-v5-global--custom-color--200 $pf-v5-global--custom-color--200 $pf-v5-color-cyan-300 #009596 | ||||
.pf-v5-c-modal-box__title.pf-m-info | --pf-v5-c-modal-box__title-icon--Color | #2b9af3 | ||
--pf-v5-c-modal-box__title-icon--Color --pf-v5-c-modal-box--m-info__title-icon--Color --pf-v5-global--info-color--100 $pf-v5-global--info-color--100 $pf-v5-color-blue-300 #2b9af3 | ||||
.pf-v5-c-modal-box__header + .pf-v5-c-modal-box__body | --pf-v5-c-modal-box__body--PaddingTop | 1rem | ||
--pf-v5-c-modal-box__body--PaddingTop --pf-v5-c-modal-box__header--body--PaddingTop --pf-v5-global--spacer--md $pf-v5-global--spacer--md pf-size-prem(16px) 1rem |
View source on GitHub