Modal
A dialog with a backdrop, Escape to close, focus return and body scroll lock.
Use Modal for a confirmation, a short form or any content that needs the customer's attention before continuing. For a side panel, use Drawer.
Example
import { useState } from 'react';
import { Modal } from '@salla.sa/twilight-theme-engine/modal';
export function ConfirmClear({ onConfirm }: { onConfirm: () => void }) {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>Clear cart</button>
<Modal isOpen={open} onClose={() => setOpen(false)} size="sm">
<Modal.Header onClose={() => setOpen(false)}>Clear the cart?</Modal.Header>
<Modal.Body>All items will be removed.</Modal.Body>
<Modal.Footer>
<button onClick={() => setOpen(false)}>Cancel</button>
<button onClick={onConfirm}>Clear</button>
</Modal.Footer>
</Modal>
</>
);
}You own the open state: the modal only asks you to close it through onClose.
API
| Prop | Type | Description |
|---|---|---|
isOpen | boolean | Whether the modal is shown. Required. |
onClose | () => void | Called on Escape or backdrop click. You set isOpen to false. Required. |
children | ReactNode | Modal content. Required. |
size? | "sm" | "md" | "lg" | "xl" | "full" | Maximum width. Default: "md". |
position? | "center" | "top" | Vertical placement. Default: "center". |
closeOnBackdropClick? | boolean | Close when the backdrop is clicked. Default: true. |
closeOnEscape? | boolean | Close on the Escape key. Default: true. |
preventBodyScroll? | boolean | Lock page scroll while open. Default: true. |
className? | string | Class on the modal panel. |
Parts: Modal.Header, Modal.Body and Modal.Footer. Each accepts normal div attributes. Modal.Header also takes showCloseButton (default true) and onClose.
Gotchas
- The close button in
Modal.Headerappears only when you passonCloseto the header too. - Always give the customer a visible way to close it (the header button or your own). Do not rely on a backdrop click alone.
- Clicking, typing and pressing Enter or Space inside the panel never close it, so forms and buttons inside work as usual. Only a backdrop click and Escape call
onClose. - It renders nothing while closed and during server rendering, and uses a portal when open.
- While open it adds the class
menu-openedto<body>, and on close focus returns to the element that had it before. ImageModalis also exported from this path and loads lazily.
Next
Draweris the side panel with the same props.toastis for short messages that need no action.- Layout and components