Modal
A blocking overlay dialog with focus trap, scroll lock, Escape-to-close, backdrop dismissal, and focus return; composed from Modal, ModalHeader, ModalTitle, ModalContent, ModalFooter, and ModalClose.
Installation
npx dafink-ui add modalDemo
Composition
<Modal>
</Modal>
Props
| Name | Type | Default | Description |
|---|---|---|---|
| open | boolean | - | Controls whether the modal is rendered and visible (controlled). |
| onOpenChange | (open: boolean) => void | - | Called with false when the user dismisses via Escape, backdrop click, or ModalClose. |
| size | 'sm' | 'md' | 'lg' | 'md' | Controls the panel max-width: sm (24rem), md (28rem), lg (48rem). Height is always content-driven; ModalContent scrolls internally if it overflows the viewport. |
| className | string | "" | Additional classes merged onto the dialog panel element. |
| children | ReactNode | - | Modal subcomponents (ModalHeader, ModalTitle, ModalContent, ModalFooter, ModalClose) and arbitrary content. |
Accessibility
Modal is a blocking overlay built on the native <dialog> element with showModal(): role="dialog", aria-modal="true", and aria-labelledby pointing at ModalTitle. Focus moves to the first focusable element inside the panel on open (or the panel itself if it has none), is fully trapped inside the panel while open (focusable elements are re-queried on every Tab press), and returns to the trigger element whenever the modal closes, however it closed.
| Key | Function |
|---|---|
| escape | Closes the modal and returns focus to the trigger. |
| tab | Moves focus to the next focusable element inside the panel, wrapping from the last back to the first (focus trap). |
| shift+tab | Moves focus to the previous focusable element inside the panel, wrapping from the first back to the last. |
| enter | Activates the focused button (native behavior). |