Modal
Modals are overlays that prevent users from interacting with the rest of the application until a specific action is taken.
Import
Modal: The wrapper that provides context for its childrenModalOverlay: The dimmed overlay behind the modal dialogModalContent: The container for the modal dialog's contentModalHeader: The header that labels the modal dialogModalFooter: The footer that houses the modal actionsModalBody: The wrapper that houses the modal's main contentModalCloseButton: The button that closes the modal.
import {Modal,ModalOverlay,ModalContent,ModalHeader,ModalFooter,ModalBody,ModalCloseButton,} from '@outfitio/outkit';
Usage
When the modal opens, focus is sent into the modal and set to the first tabbable element. If there are no tabbled
element, focus is set on the ModalContent.
Control Focus when modal closes
When the dialog closes, it returns focus to the element that triggered. Set finalFocusRef to element that should
receive focus when the modal closes.
Focus on specific element
Focus is automatically set on the first tabbable element in the modal. However, there might be scenarios where you need to manually control where focus goes.
There are 2 props for this use-case:
initialFocusRef: Therefof the component that receives focus when the modal opens.finalFocusRef: Therefof the component that receives focus when the modal closes.
If you set
finalFocusRef, internally we setreturnFocusOnClosetofalseso it doesn't return focus to the element that triggered it.
Close modal on overlay click
By default, the modal closes when you click it's overlay. You can set closeOnOverlayClick to false if you want the
modal to stay visible.
You should always disable closeOnOverlayClick if the modal prompts the user to enter data, such as filling out a form
field. In these instances, an accidental misclick could result in the user losing all progress, requiring them to start
again.
Make modal vertically centered
By default the modal has a vertical offset of 3.75rem which you can change by passing top to the ModalContent. If
you need to vertically center the modal, pass the isCentered
If the content within the modal overflows beyond the viewport, don't use this prop. Try setting the overflow behavior instead
Adding transition
The modal doesn't come with any transition by default so you can manage this yourself. Outkit exports two transition
components SlideIn and Scale to provide simple transitions.
For some reason, focus doesn't return back to the trigger after the transition ends. As a walkaround, you might need to set
finalFocusRefto the trigger or any other element, and setisOpentotrue.
Modal overflow behavior
If the content within the modal overflows beyond the viewport, you can use the scrollBehavior to control how scrolling
should happen.
- If set to
inside, scroll only occurs within theModalBody. - If set to
outside, the entireModalContentwill scroll within the viewport.
Modal sizes
Pass the size prop if you need to adjust the size of the modal. Values can be xs, sm, md, lg, xl, or full.
Preserving the scrollbar gap
By default, scrolling is blocked when the modal opens. This can lead to unpleasant content shift.
To prevent this, pass the preserveScrollBarGap prop. It applies a padding-right to the body element that's equal to
the width of the browser's scrollbar.
Making other elements inert
When the modal is open, it's rendered within a portal and all it's siblings have aria-hidden set to true so the only
thing screen readers see is the modal. To disable this behavior, set useInert to false.
Accessibility
ARIA roles
- The
ModalContenthasaria-modalset totrue. - The
ModalContenthasaria-labelledbyset to theidof theModalHeader - The
ModalContenthasaria-describedbyset to theidof theModalBody
Keyboard support
- When the modal opens, focus is trapped within it.
- When the dialog opens, focus is automatically set to the first enabled element, or the element with the
initialFocusRef. - When the modal closes, focus returns to the element that was focused just before the modal activated, or the element
with the
finalFocusRef - Clicking on the overlay closes the Modal.
- Pressing Esc closes the Modal.
- Scrolling is blocked on the elements behind the modal.
- The modal is portalled to the end of
document.bodyto break it out of the source order and make it easy to addaria-hiddento its siblings.
Best Practice
- Use modals when users must complete an action before they can continue with the main workflow.
- Avoid complex decision making that requires consulation of information unavailable in the modal.
- In general, try to limit the number of interactions in a modal dialog. Simplify by removing unnecessary elements or content that does not support the task.
- Additionally, modals should have no more than one primary action button. This primary action should reflect the modal title.
- Body content should always put the most critical information first
- Labels for buttons and actions should clearly indicate what will happen when the element is selected. For example, label a button with "Delete user" instead of simply "Delete".
- Set
closeOnOverlayClicktofalseif the modal prompts the user to enter data, such as filling out a form field.
Props
Modal Props
| Name | Type | Default | Description |
|---|---|---|---|
| isOpen | boolean | If true, the modal will open | |
| onClose | (event, reason) => void | Callback invoked to close the modal. | |
| isCentered | boolean | If true, the Modal will be centered on screen | |
| initialFocusRef | React.Ref | The ref of the element to receive focus when the dialog opens | |
| finalFocusRef | React.Ref | The ref of element to receive focus when the dialog closes | |
| blockScrollOnMount | boolean | true | If true, scrolling will be disabled on the body when the modal opens. |
| preserveScrollBarGap | boolean | If true, a padding-right will be applied to the body element to preserve the scrollbar gap. | |
| useInert | boolean | true | A11y: If true, all elements behing the Modal will have aria-hidden |
to true so that screen readers can only see the Modal. | |||
| children | React.ReactNode | The content of the modal. | |
| size | BoxProps["maxWidth"] | md | The size (maxWidth) of the modal. |
| scrollBehavior | inside, outside | outside | Where scroll behaviour should originate. |
| closeOnOverlayClick | boolean | true | If true, the modal will close when the overlay is clicked |
| returnFocusOnClose | boolean | true | If true, the modal will return focus to the element that triggered it when it closes. |
| closeOnEsc | boolean | true | If true, the modal will close when the Esc key is pressed |
| addAriaLabels | boolean, {header: boolean, body: boolean} | true | If false, no aria-* properties will be added by default. |
| id | string | The id of the modal |
Other components
ModalOverlay,ModalHeader,ModalFooterandModalBodycomposesBoxcomponentModalCloseButtoncomposesCloseButton