Modal Component
The Modal component is a flexible and composable overlay system designed for dialogs, confirmations, and complex UI interactions. It includes structured subcomponents like ModalContent, ModalHeader, ModalBody, and ModalFooter — making it easy to build consistent, accessible layouts.
Use ModalTriggerButton for quick integration, disableOverlayClose to control dismiss behavior, and ModalButton for built-in actions with optional async handling. The component also supports animations via framer-motion and full styling control through className and style props.
Import Component From Library
1import {
2 Modal,
3 ModalContent,
4 ModalHeader,
5 ModalBody,
6 ModalFooter,
7 ModalButton,
8 ModalTriggerButton,
9 Button
10} from "@neuctra/ui";Basic Usage Code
Start with a simple modal. The component provides overlay dialogs with structured layouts, animations, and full customization.
1import { useState } from 'react';
2import {
3 Modal,
4 ModalContent,
5 ModalHeader,
6 ModalBody,
7 ModalFooter,
8 Button
9} from '@neuctra/ui';
10
11function BasicExample() {
12 const [open, setOpen] = useState(false);
13
14 return (
15 <>
16 <Button onClick={() => setOpen(true)}>
17 Open Modal
18 </Button>
19
20 <Modal isOpen={open} onClose={() => setOpen(false)}>
21 <ModalContent onClose={() => setOpen(false)}>
22 <ModalHeader title="Modal Title" onClose={() => setOpen(false)} />
23 <ModalBody>
24 <p>Modal content goes here</p>
25 </ModalBody>
26 <ModalFooter>
27 <Button variant="ghost" onClick={() => setOpen(false)}>
28 Cancel
29 </Button>
30 <Button onClick={() => setOpen(false)}>
31 Confirm
32 </Button>
33 </ModalFooter>
34 </ModalContent>
35 </Modal>
36 </>
37 );
38}Basic Example
Modal Props
| Prop | Type | Default | Description |
|---|---|---|---|
| isOpen | boolean | false | Controls modal visibility |
| onClose | () => void | — | Triggered on ESC or overlay click |
| disableOverlayClose | boolean | false | Prevents closing on overlay click (also blocks Escape unless disableEscapeClose says otherwise) |
| disableEscapeClose | boolean | disableOverlayClose | Also blocks the Escape key |
| ariaLabel | string | — | Accessible name for the dialog when no ModalHeader is used |
| style | CSSProperties | — | Overlay wrapper styles |
| overlayClassName | string | — | Overlay background class |
| overlayStyle | CSSProperties | — | Overlay inline styles |
| dialogClassName | string | — | Styles the role="dialog" wrapper around children |
ModalButton Props
| Prop | Type | Default | Description |
|---|---|---|---|
| onClick | () => void | — | Runs before action |
| action | () => void | Promise | — | Async action before close |
| closeOnClick | boolean | false | Closes modal after action |
| onClose | () => void | — | Called after action completes |
| loading | boolean | — | Shows loading state |
ModalContent Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | Modal content |
| className | string | — | Container class |
| style | CSSProperties | — | Container styles |
| maxWidth | string | max-w-md | Maximum width class |
| onClose | () => void | — | Closes modal |
| showCloseButton | boolean | false | Show top-right close button |
| closeButtonClassName | string | — | Close button class |
| closeButtonStyle | CSSProperties | — | Close button styles |
ModalHeader Props
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | — | Modal title |
| icon | ReactNode | — | Optional icon |
| onClose | () => void | — | Close function |
| className | string | — | Header wrapper class |
| style | CSSProperties | — | Header wrapper styles |
| titleWrapperClassName | string | — | Styles the wrapper around icon + title |
| iconClassName | string | — | Styles the icon |
| titleClassName | string | — | Styles the title heading |
| closeButtonClassName | string | — | Styles the close button |
ModalBody Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | Modal body content |
| className | string | — | Body wrapper class |
| style | CSSProperties | — | Body wrapper styles |
ModalFooter Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | Footer actions |
| className | string | — | Footer wrapper class |
| style | CSSProperties | — | Footer wrapper styles |
ModalTriggerButton Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | Trigger button label |
| modalContent | (close) => ReactNode | — | Render function for modal content |
| modalProps | Omit<ModalProps, "isOpen" | "onClose" | "children"> | — | Forwarded to the underlying Modal |
Usage Notes
- Modal automatically locks scroll when open.
- Supports ESC key to close.
- Traps keyboard focus inside the dialog while it's open.
- Overlay click behavior is configurable.
- Use
ModalButtonfor async-safe actions. - Prefer
ModalTriggerButtonfor simple modal flows. - Enable
showCloseButtononModalContentfor a top-right close icon.
Frequently Asked Questions
How do I install and import the Modal component?
Install the @neuctra/ui package, then import it with: import { Modal } from "@neuctra/ui";
Can I customize the Modal component's appearance?
Yes. Modal accepts a className prop for custom Tailwind CSS classes, so you can adjust spacing, layout, and styling without overriding the component internals.
Is the Modal component accessible?
Modal is built with semantic HTML and standard ARIA attributes, and supports keyboard navigation and focus states out of the box, so it works well with screen readers and keyboard-only users.