# Dialog

Modal interruptions on the native `<dialog>`: focus stays inside, Escape closes it and the page behind is inert.

Renders: `dialog` · Intents: [5](#intents-it-renders) · Domains: [`dialog.*`](https://www.prongs.dev/docs/intents/dialog.md)

## Examples

### Confirming a decision

You keep `open` in state. Escape, a click outside and the Cancel button all close it.

```tsx
function Confirm() {
  const [asking, setAsking] = useState(false);
  const deleteProject = () => setAsking(false);
  return (
    <>
      <Action intent="action.delete" onClick={() => setAsking(true)}>Delete project</Action>
      <Dialog intent="dialog.confirm" open={asking} onClose={() => setAsking(false)} label="Delete this project?">
        <Layout intent="layout.section">
          <Text intent="heading.item" as="h2">Delete this project?</Text>
          <Text intent="text.body">The project and all its data will be gone for good.</Text>
          <Layout intent="layout.actions">
            <Action intent="action.cancel" onClick={() => setAsking(false)}>Cancel</Action>
            <Action intent="action.delete" onClick={deleteProject}>Delete</Action>
          </Layout>
        </Layout>
      </Dialog>
    </>
  );
}
```

## Intents it renders

One domain, with its own page of neighbours and examples. The intent decides the element; these are the starter intents.

### Dialog [`dialog.*`](https://www.prongs.dev/docs/intents/dialog.md)

5 intents

| Intent | Use it for | Resolves to |
|---|---|---|
| [`dialog.task`](https://www.prongs.dev/docs/intents/dialog/task.md) | A focused task that blocks the page until done or dismissed: edit settings, compose | `<dialog>` |
| [`dialog.confirm`](https://www.prongs.dev/docs/intents/dialog/confirm.md) | Asks the user to confirm or cancel one decision | `<dialog>` |
| [`dialog.media`](https://www.prongs.dev/docs/intents/dialog/media.md) | Shows one photo or video large over the dimmed page, with its details beside it: who posted it, the caption, comments. A click outside closes it. On small screens it fills the screen, the photo between its title and its details | `<dialog>` |
| [`dialog.reader`](https://www.prongs.dev/docs/intents/dialog/reader.md) | Shows one piece of content over the whole screen: reading an article | `<dialog>` |
| [`dialog.drawer`](https://www.prongs.dev/docs/intents/dialog/drawer.md) | A full-height panel that slides in from the side over the dimmed page: site navigation on a small screen. A click outside closes it | `<dialog>` |

## Props

Plus its element’s usual attributes (`id`, `onClick`, `aria-*`, `data-*`). No `className` or `style`.

| Prop | Type | What it does |
|---|---|---|
| `intent` (required) | `DialogIntent` | [`dialog.task`](https://www.prongs.dev/docs/intents/dialog/task.md), [`dialog.confirm`](https://www.prongs.dev/docs/intents/dialog/confirm.md) or [`dialog.reader`](https://www.prongs.dev/docs/intents/dialog/reader.md). |
| `open` (required) | `boolean` | Whether it is showing. You keep it in state. |
| `onClose` (required) | `() => void` | Called on Escape, a click outside, or when it closes itself. |
| `label` (required) | `string` | The accessible name: usually the heading text. |
| `children` (required) | `ReactNode` | The content. It renders only while the dialog is open. |
| `unsafeClassName` | `string` | Bypasses the intent. Needs a `// prongs-unsafe: <reason>` comment on the line above, and `prongs check` counts it. |

## Rules

- Put a heading, the content and a [`layout.actions`](https://www.prongs.dev/docs/intents/layout/actions.md) row inside.
- Keep `open` in state and set it to false in `onClose`.
