<!-- Generated by scripts/build-agent-kit.ts for @aistrike-dev/ui@5.0.1. Do not edit. -->

# Dialog vs Drawer vs Popover vs Modal

<!-- use-when: Putting content on top of the page: which overlay surface, and never Modal. -->

Every one of these puts content on top of the page, which is why they get swapped for each other. They
differ in two ways that the user feels immediately: **whether the overlay belongs to a specific element
on the page**, and **whether the user can keep working behind it**.

| Surface | Anchored to an element | Blocks the page | Room for content |
| --- | --- | --- | --- |
| `Dialog` | No — centred | Yes, traps focus | A confirmation or a short form |
| `Drawer` | Edge of the viewport | `temporary` yes, `persistent`/`permanent` no | A lot — details, filters, a long form |
| `Popover` | Yes, to `anchorEl` | No | A little — a detail card, a mini-form |
| `Menu` | Yes, to `anchorEl` | No | A list of actions, nothing else |
| `Tooltip` | Yes, to its child | No | One line of text |
| `Modal` | No | Yes | Anything — it is an unstyled primitive |

`Modal` is `llmSafe: false`. It is the bare overlay primitive with no surface, padding, title or action
row, so choosing it means rebuilding `Dialog` by hand. **Never generate a `Modal`.** If `Dialog` and
`Drawer` both feel wrong, that is the signal to ask, not to drop to the primitive.

## Decision flow

```
Is it one line of explanatory text for a control?
        │
        ├── Yes ─────────────────────────────────► Tooltip
        └── No
                │
                ├── Is it purely a list of actions triggered from a control?
                │        └── Yes ────────────────► Menu
                │
                ├── Must the user deal with it before doing anything else?
                │        │
                │        ├── Yes
                │        │     ├── Confirmation or short form ──► Dialog
                │        │     └── Long form, or needs the page
                │        │         visible for context ─────────► Drawer (temporary)
                │        └── No
                │              ├── Belongs to a specific element on
                │              │   the page, and is small ──────► Popover
                │              └── A side region of the screen
                │                  that stays put ─────────────► Drawer (persistent/permanent)
                │
                └── None of these fit ───────────► Ask. Do not reach for Modal.
```

## Dialog

The default blocking overlay. Use it for **a decision or a short task the user must finish or abandon
before continuing**.

**Reach for it when:**

- Confirming something consequential: "Delete 12 assets?", "Isolate this host?"
- A short focused form: rename, invite a user, add a tag.
- Showing a result the user must acknowledge before the page is usable again.

```tsx
import { Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button } from '@aistrike-dev/ui';

<Dialog open={open} onClose={close} maxWidth="sm" fullWidth>
  <DialogTitle>Isolate host?</DialogTitle>
  <DialogContent>
    <DialogContentText>
      This cuts network access for web-01 until you restore it.
    </DialogContentText>
  </DialogContent>
  <DialogActions>
    <Button variant="ghost" onClick={close}>Cancel</Button>
    <Button variant="destructive" onClick={isolate}>Isolate host</Button>
  </DialogActions>
</Dialog>
```

**Practical limits:** the theme owns `DialogActions` padding and alignment — adjust with the `align`
and `dense` props, never with `sx`. Never stack one dialog on another; if a dialog needs to open a
second decision, the flow belongs on a page or in a `Drawer` with a `Stepper`. If the content scrolls
more than a little, it is too big for a dialog.

## Drawer

A panel from an edge of the viewport. Use it when there is **more content than a dialog can hold**, or
when the user needs to **see the page behind it** while working.

**Reach for it when:**

- Inspecting one row of a table without leaving the list.
- A filter panel the user tunes while watching results change.
- A long or multi-step form.
- Navigation on narrow viewports.

```tsx
import { Drawer, Typography } from '@aistrike-dev/ui';
import { Box } from '@mui/material';

<Drawer anchor="right" open={open} onClose={close}>
  <Box sx={{ p: 3, width: 360 }}>
    <Typography variant="h6">prod-db-01</Typography>
    <Typography variant="body1" color="text.secondary">
      Finding detail. Give every drawer a heading — it is a landmark, not a floating box.
    </Typography>
  </Box>
</Drawer>
```

**Practical limits:** pick `variant` deliberately — `temporary` traps focus and closes on Esc or
backdrop click, `persistent` and `permanent` do not and coexist with the page. A `temporary` drawer is
never the home for primary app navigation; that is `LeftNavigation`. Always give a drawer a visible
heading so it reads as a region rather than an unexplained slab.

## Popover

A small overlay **anchored to the element that opened it**, which the user can dismiss by clicking away.
It is for content that only makes sense in relation to that element.

**Reach for it when:**

- A detail card on a chart point, a table cell, or an avatar.
- A colour picker, a date-range picker, a two-field mini-form.
- A "why is this severity?" explanation richer than one line of text.

```tsx
import { Popover, Typography } from '@aistrike-dev/ui';
import { Box } from '@mui/material';

<Popover
  open={Boolean(anchorEl)}
  anchorEl={anchorEl}
  onClose={() => setAnchorEl(null)}
  anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
>
  <Box sx={{ p: 2, maxWidth: 280 }}>
    <Typography variant="subtitle2">prod-db-01</Typography>
    <Typography variant="body1" color="text.secondary">
      Keep this short — a form belongs in a Dialog or Drawer.
    </Typography>
  </Box>
</Popover>
```

**Practical limits:** `anchorEl` is required, so a popover with no triggering element is the wrong
choice. Keep it to a handful of fields at most. If the content is just one line of text, use `Tooltip`;
if it is only actions, use `Menu`.

## Modal

The unstyled primitive underneath `Dialog`. Marked `llmSafe: false` precisely because reaching for it
means reimplementing the surface, spacing, title and action row the theme already provides.

Do not generate it. If neither `Dialog` nor `Drawer` fits, ask:

> "This needs a full-bleed overlay for the attack-path canvas, which isn't a `Dialog` or a `Drawer`.
> Should I build it as a full page route instead, or do you want a new component in the design system?"

## Worked examples

| Scenario | Surface | Why |
| --- | --- | --- |
| "Delete 12 selected findings?" | `Dialog` | A decision that must be resolved first |
| Rename an asset | `Dialog` | Short focused form |
| Finding detail, opened from a table row | `Drawer` (`anchor="right"`) | Too much content for a dialog; the list stays visible |
| Filter panel tuned against live results | `Drawer` (`persistent`) | The user watches the page change while adjusting |
| Multi-step "Connect integration" flow | `Drawer` + `Stepper`, or a page | Sequential and long |
| Hovering a chart point to see its detail card | `Popover` | Anchored to that point, non-blocking |
| Date-range selection on a dashboard | `Popover` | Anchored, small, dismissible |
| Row overflow "..." with Edit / Duplicate / Delete | `Menu` | A list of actions and nothing else |
| Explaining what an icon button does | `Tooltip` | One line of text |
| A full-bleed custom canvas overlay | Ask | Do not drop to `Modal` |
| Navigation on a phone-width viewport | `Drawer` (`temporary`) | Standard mobile pattern |

## Anti-patterns

- **Reaching for `Modal`.** It is `llmSafe: false`. Anything you build on it, `Dialog` already does
  better.
- **Stacking dialogs.** A dialog that opens another dialog leaves the user with no idea what closing
  does. Use one dialog, or move the flow to a drawer or a page.
- **Padding `DialogActions` with `sx`.** The theme owns that spacing; use `align` and `dense`.
- **A long form in a `Dialog`.** Once the body scrolls, the actions drift out of view and the user
  loses the exit. Use a `Drawer` or a page.
- **A form in a `Popover`.** Popovers dismiss on outside click, so a half-filled form is one stray
  click from being lost.
- **A `temporary` `Drawer` as primary navigation.** Primary navigation is always visible;
  `LeftNavigation` with `collapsed` is the pattern.
- **A `Popover` with no anchor**, positioned manually. If there is no anchoring element, it is a
  `Dialog`.
- **A `Menu` holding non-action content.** Menus are lists of verbs. Content goes in a `Popover`.
- **Essential information only in a `Tooltip`.** It is invisible on touch and to anyone not hovering.

## Accessibility

- `Dialog` traps focus, closes on Esc and backdrop click, and takes its accessible name from
  `DialogTitle` — so always include one.
- `Drawer` traps focus only in the `temporary` variant. Give every drawer a heading; for
  `persistent`/`permanent` drawers, that heading is the only thing telling a screen-reader user what
  the region is.
- `Popover` and `Menu` both close on Esc and return focus to the anchor. Do not reimplement this.
- `Tooltip` needs a focusable child, so keyboard users can reach it. Wrap a disabled element in a
  `span`, or the tooltip never fires.
- `Modal` provides none of the above for free — another reason not to use it.

## When you are unsure, ask

The genuinely ambiguous case is **`Dialog` vs `Drawer`**: it depends on how much content there is and
whether the user needs the page behind it, and a mockup often does not settle either. **If you cannot
confidently choose, stop and ask before building — name the two options and say which you lean toward
and why.**

> "The finding detail opens from a table row. I'm leaning toward a right-hand `Drawer` so the list
> stays visible and the user can move between rows, rather than a `Dialog`. Is that the behaviour you
> want, or should it be a full page?"

> "This confirmation also needs a reason field and a notify-team checkbox. That is still small enough
> for a `Dialog` in my view, but if more fields are coming it should be a `Drawer`. How much is this
> going to grow?"

A single clarifying question is far cheaper than shipping a control whose behaviour surprises the user.

## References

- **Organisms → Dialog**, **Organisms → Drawer**, **Molecules → Popover**, **Molecules → Menu**,
  **Atoms → Tooltip** — stories for each surface.
- **Guidelines → Choosing → Navigation** — where `Drawer` fits against `LeftNavigation`.
- [MUI Dialog](https://mui.com/material-ui/react-dialog/) · [MUI Drawer](https://mui.com/material-ui/react-drawer/) · [MUI Popover](https://mui.com/material-ui/react-popover/) · [MUI Menu](https://mui.com/material-ui/react-menu/)
