{
  "title": "AlertDialog",
  "description": "Confirmation modal that forces a user response — no escape, no click-outside.",
  "url": "/docs/components/alert-dialog",
  "since": "0.3.0",
  "tags": [
    "overlay",
    "confirmation",
    "destructive"
  ],
  "platform": "both",
  "source": "---\ntitle: AlertDialog\ndescription: Confirmation modal that forces a user response — no escape, no click-outside.\nsince: 0.3.0\ntags: [overlay, confirmation, destructive]\nplatform: both\ncategory: overlays\n---\n\nimport { BundleSize } from '@/components/bundle-size';\nimport { Callout } from 'fumadocs-ui/components/callout';\nimport { Preview } from '@/components/preview';\nimport { PropsTable } from '@/components/props-table';\n\n<BundleSize component=\"AlertDialog\" />\n\n## At a glance\n\n- Compose: `AlertDialog`, `AlertDialogTrigger`, `AlertDialogContent`, `AlertDialogTitle`, `AlertDialogDescription`, `AlertDialogCancel`, `AlertDialogAction`, `AlertDialogFooter`. Triggers / Cancel / Action use `asChild` by default — wrap any element and it becomes the activator.\n- Forces a response: backdrop click does **not** close, Escape does **not** close. The user MUST press Cancel or Action.\n- Initial focus lands on Cancel — the least destructive default — so a stray Enter keypress can't fire the destructive action.\n- Accessibility: `role=\"alertdialog\"` with `aria-modal`, `aria-labelledby` on the title, `aria-describedby` on the description.\n- Cross-platform: uses RN `<Modal>` as the visibility primitive. Web layers on focus trap, scroll lock, focus restore. Subtle scale-in animation (150ms) honors `prefers-reduced-motion`.\n\n<Callout type=\"warn\" title=\"When to use AlertDialog vs Dialog\">\n    Use **`AlertDialog`** for destructive or otherwise irreversible confirmations — \"Delete project?\", \"Sign out\n    everyone?\", \"Discard unsaved changes?\". The user has to make an explicit choice, which matches the weight of the\n    action.\n\n    Use **`Dialog`** for everything else — forms, info, settings, embedded flows. Dialog allows Escape and click-outside\n    to dismiss, which is the expected affordance for forgettable, low-stakes interactions.\n\n    Choosing the wrong one is a real accessibility / UX bug: if Dialog gates a destructive action, users will lose work\n    by tapping outside; if AlertDialog gates a form, users will feel trapped.\n</Callout>\n\n## Preview\n\n<Preview name=\"alert-dialog-destructive\" />\n\n## Open state — `open`, `defaultOpen`, `onOpenChange`\n\n`open` (controlled) + `onOpenChange` is the parent-driven shape; pass\n`defaultOpen` for uncontrolled mode. Mixing the two prefers controlled\nand ignores `defaultOpen`. Trigger / Cancel / Action subcomponents\nalready flip the state for you, so most call sites don't need either.\n\n```tsx\nconst [open, setOpen] = useState(false);\n<AlertDialog open={open} onOpenChange={setOpen}>...</AlertDialog>\n```\n\n## Anatomy\n\n| Subcomponent | Role |\n|---|---|\n| `AlertDialog` | Root — owns open state (controlled or uncontrolled). |\n| `AlertDialogTrigger` | Element that opens the dialog. `asChild` by default. |\n| `AlertDialogContent` | The visible surface. Renders only while open. Backdrop click and Escape do nothing. |\n| `AlertDialogTitle` | Heading. Wires `aria-labelledby`. |\n| `AlertDialogDescription` | Body description. Wires `aria-describedby`. |\n| `AlertDialogCancel` | Dismiss action. Receives initial focus. Forwards `onPress`, then closes. |\n| `AlertDialogAction` | Confirming / destructive action. Forwards `onPress`, then closes. |\n| `AlertDialogFooter` | Right-aligned row for the Cancel / Action buttons. |\n\n## Usage\n\n```tsx\nimport {\n    AlertDialog,\n    Button,\n} from '@nori-ui/core';\n\nexport function DeleteProjectButton({ onDelete }: { onDelete: () => void }) {\n    return (\n        <AlertDialog>\n            <AlertDialog.Trigger>\n                <Button variant=\"destructive\">Delete project</Button>\n            </AlertDialog.Trigger>\n            <AlertDialog.Content>\n                <AlertDialog.Title>Delete this project?</AlertDialog.Title>\n                <AlertDialog.Description>\n                    This permanently removes the project and every record attached to it. This cannot be undone.\n                </AlertDialog.Description>\n                <AlertDialog.Footer>\n                    <AlertDialog.Cancel>\n                        <Button variant=\"secondary\">Cancel</Button>\n                    </AlertDialog.Cancel>\n                    <AlertDialog.Action onPress={onDelete}>\n                        <Button variant=\"destructive\">Delete project</Button>\n                    </AlertDialog.Action>\n                </AlertDialog.Footer>\n            </AlertDialog.Content>\n        </AlertDialog>\n    );\n}\n```\n\n## Props\n\n### AlertDialog\n\n<PropsTable component=\"AlertDialog\" />\n\n### AlertDialogTrigger\n\n<PropsTable component=\"AlertDialogTrigger\" />\n\n### AlertDialogContent\n\n<PropsTable component=\"AlertDialogContent\" />\n\n### AlertDialogCancel\n\n<PropsTable component=\"AlertDialogCancel\" />\n\n### AlertDialogAction\n\n<PropsTable component=\"AlertDialogAction\" />\n"
}
