Modal
A centred dialog for a decision that must be made before continuing — a confirmation, a short form. Built on the native <dialog>, so focus trapping and the backdrop come from the platform.
import Modal from '@/components/ui/Modal';Source: src/components/ui/Modal.tsx
Examples
A confirmation
The footer is where actions go, and the destructive one goes last. Cancel first means the safe option is the one under your cursor when the dialog appears.
Props
<Modal> props
| Prop | Type | Default | Description |
|---|---|---|---|
openrequired | boolean | — | — |
onCloserequired | () => void | — | — |
title | string | — | — |
footer | ReactNode | — | Action row rendered bottom-right, e.g. a cancel Button + confirm Button. |
className | string | '' | — |
childrenrequired | ReactNode | — | — |
Accessibility
- Native <dialog>: focus moves in on open, is trapped while open, and returns to the trigger on close.
- Escape closes it, and so does a backdrop click.
Usage
Do
- Give it a title. It is the dialog’s accessible name as well as its heading.
- Keep the content short enough not to scroll.
Don’t
- Don’t use a raw <dialog>. ESLint blocks it, and the reason is in this component: a closed dialog is hidden by the UA stylesheet, and an author `display` beats the UA origin — so a bare `flex` class makes a closed dialog visible. It has to be `open:flex`.
- Don’t open a modal from another modal.
- Don’t put a long form in one — that is a page.