Destructive actions
Irreversible or high-impact actions get a confirmation that names the object and states the consequence. The destructive button uses the AA-safe danger-action fill, the safe action takes initial focus, and the confirm can run async — blocking re-submission and staying open if it fails.
Confirm before deleting
<ConfirmDialog trigger={<Button variant="destructive">Delete project</Button>} title="Delete project" objectName="Apollo" description="This permanently deletes Apollo and all of its data. This cannot be undone." confirmLabel="Delete" onConfirm={async () => { await deleteProject(id); // async: dialog waits, then closes on success }}/>Rules
- Name the object in the heading and restate the consequence in the body.
- The safe action (Cancel) receives initial focus, so a stray Enter cancels rather than destroys.
- Use
Button variant="destructive"for the confirming action — never a hand-rolled red button or a status-danger fill. onConfirmmay be async: the button shows a spinner, both actions block re-submission, and a rejection leaves the dialog open so the error can be surfaced.- For the highest-risk actions (deleting a workspace), require the object name to be typed before enabling confirm.