Modal
A dialog overlay component for confirmations, forms, and focused content. Supports multiple sizes, keyboard navigation, focus trapping, and smooth spring-based animations via Framer Motion.
Live Preview
Open a modal with title, description, body content, and footer actions.
1const [open, setOpen] = useState(false);2 3<AidashButton onClick={() => setOpen(true)}>Open Modal</AidashButton>4 5<Modal6open={open}7onClose={() => setOpen(false)}8title="Confirm Action"9description="Please review the details below before proceeding."10footer={11 <>12 <AidashButton variant="outline" onClick={() => setOpen(false)}>Cancel</AidashButton>13 <AidashButton onClick={() => setOpen(false)}>Confirm</AidashButton>14 </>15}16>17<p>This is the modal body content.</p>18</Modal>Installation
Install the Aidash Components package using your preferred package manager.
$ pnpm add @aidash/componentsImport
Import the Modal component into your file.
import { Modal } from '@/components/aidash/modal';Sizes
Five size presets to fit different content types: sm, md, lg, xl, and fullscreen.
1<Modal size="sm">...</Modal>2<Modal size="md">...</Modal> {/* default */}3<Modal size="lg">...</Modal>4<Modal size="xl">...</Modal>5<Modal size="fullscreen">...</Modal>Footer Alignment
Control horizontal alignment of the footer action row via footerAlign (start / between / end).
1<Modal2 footerAlign="between"3 footer={<>4 <AidashButton variant="ghost">Cancel</AidashButton>5 <AidashButton>Confirm</AidashButton>6 </>}7>8 ...9</Modal>Initial Focus
Route initial focus to a specific field on open via initialFocusRef, instead of the default first focusable descendant.
1const emailInputRef = useRef<HTMLInputElement>(null);2 3<Modal4 open={open}5 onClose={onClose}6 initialFocusRef={emailInputRef}7>8 <input ref={emailInputRef} type="email" />9</Modal>With Footer
Use the footer slot to render action buttons separated by a top border.
1<Modal2open={open}3onClose={onClose}4title="Save Changes"5description="You have unsaved changes that will be lost."6footer={7 <>8 <AidashButton variant="ghost" onClick={onClose}>Discard</AidashButton>9 <AidashButton variant="outline" onClick={onClose}>Save Draft</AidashButton>10 <AidashButton onClick={onClose}>Publish</AidashButton>11 </>12}13>14<p>Your document contains unsaved changes.</p>15</Modal>Controlled Close
Fine-tune how the modal can be dismissed: overlay click, Escape key, and close button.
1<Modal2open={open}3onClose={onClose}4title="Controlled Modal"5closeOnOverlay={false} // Prevent closing on overlay click6closeOnEscape={false} // Prevent closing on Escape key7showClose={false} // Hide the X close button8footer={<AidashButton onClick={onClose}>Close</AidashButton>}9>10<p>Only the footer button can close this modal.</p>11</Modal>API Reference
Complete list of props accepted by Modal.
| Prop | Type | Default | Description |
|---|---|---|---|
| open* | boolean | — | Whether the modal is visible |
| onClose* | () => void | — | Callback when the modal requests to close |
| size | 'sm' | 'md' | 'lg' | 'xl' | 'fullscreen' | 'md' | Width preset for the modal panel |
| title | string | — | Heading rendered in the modal header |
| description | string | — | Subtitle text below the title |
| children* | ReactNode | — | Main body content of the modal |
| footer | ReactNode | — | Footer slot, typically action buttons |
| footerAlign | 'start' | 'between' | 'end' | 'end' | Horizontal alignment of footer content |
| closeOnOverlay | boolean | true | Close when clicking the backdrop overlay |
| closeOnEscape | boolean | true | Close when pressing the Escape key |
| showClose | boolean | true | Show the X close button in the header |
| initialFocusRef | RefObject<HTMLElement | null> | — | When provided and inside the modal, this element receives focus on open instead of the first focusable |
| className | string | '' | Additional CSS classes on the panel |
footer slot renders inside a flex container with justify-end and gap-3, so buttons align automatically.Accessibility
Built-in accessibility features for screen readers, keyboard navigation, and focus management.
Dialog ARIA Role
The modal panel uses role="dialog" and aria-modal="true" to announce itself correctly to assistive technology. Title and description are linked via aria-labelledby and aria-describedby.
Focus Trap
When open, the modal prevents background scrolling by setting overflow: hidden on the body. The overlay blocks interaction with elements behind the dialog.
Keyboard Navigation
Press Escape to close the modal (configurable via closeOnEscape). The close button has an aria-label="Close modal" for screen reader users.
Scroll Lock
Background page scroll is automatically disabled when the modal is open and restored when it closes. Long modal content scrolls within the panel via overflow-y-auto.
1{/* ARIA attributes are applied automatically */}2<Modal3open={open}4onClose={onClose}5title="Accessible Modal" // → aria-labelledby6description="Helpful context" // → aria-describedby7closeOnEscape={true} // → Escape key handler8>9{/* role="dialog" aria-modal="true" applied to panel */}10<p>Content is accessible by default.</p>11</Modal>Related
Other components that work well alongside Modal.