# Modal (https://docs.salla.dev/twilight/react/components/modal)



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`](https://docs.salla.dev/twilight/react/components/drawer).

## Example [#example]

```tsx title="app/components/cart/ConfirmClear.tsx"
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 [#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 [#gotchas]

* The close button in `Modal.Header` appears only when you pass `onClose` to 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-opened` to `<body>`, and on close focus returns to the element that had it before.
* `ImageModal` is also exported from this path and loads lazily.

## Next [#next]

* [`Drawer`](https://docs.salla.dev/twilight/react/components/drawer) is the side panel with the same props.
* [`toast`](https://docs.salla.dev/twilight/react/components/toast) is for short messages that need no action.
* [Layout and components](https://docs.salla.dev/twilight/react/guide/layout-and-components)
