The problem
“Are you sure?” with OK and Cancel trains people to press OK without reading. The dialog doesn't say what will be lost, and the buttons don't say what they do. Meanwhile actions that could simply be undone get a confirmation they don't need.
When to use it
Use it for
- The action can't be undone: deleting an account, sending payroll, revoking access.
- The action affects other people, or many items at once.
Not for
- The action can be undone: do it straight away and offer Undo in a Toast.
- Routine actions like archiving or moving: a confirmation adds friction and no safety.
Anatomy
- TriggerA destructive Button that names the action, such as “Delete request”.
- Alert dialogrole=alertdialog. The title names the object; the body says what will be lost.
- Primary actionRepeats the verb and the object. Styled destructive.
- Safe action“Keep request”, not “Cancel”. Receives focus when the dialog opens.
- ConfirmationA Toast after the action, saying what happened.
How to build it
- Ask first: can this be undone? If yes, skip the dialog and use an Undo toast instead.
- Write the title as a question that names the object: “Delete Sara's leave request?”.
- In the body, say what will be lost and that it can't be undone.
- Label the buttons with verbs: “Delete request” and “Keep request”.
- Use variant="destructive" and role="alertdialog".
- After deleting, move focus somewhere sensible and confirm with a Toast.
app.tsx
import { Button, Dialog, useToast } from "@nexera-ui/react";
export function DeleteRequest({ request }: Props) {
const toasts = useToast();
return (
<Dialog
variant="destructive"
role="alertdialog"
title={`Delete ${request.owner}'s leave request?`}
body={`Their request for ${request.dates} will be removed. This can't be undone.`}
primaryLabel="Delete request"
secondaryLabel="Keep request"
onPrimaryAction={async () => {
await deleteRequest(request.id);
toasts.add({ title: "Leave request deleted", tone: "success" });
}}
trigger={<Button variant="destructive">Delete request</Button>}
/>
);
}Accessibility
| Key | Action |
|---|---|
| Enter | Activates the focused button. |
| Escape | Closes the dialog without deleting. |
| Tab | Moves between the buttons; focus stays inside the dialog. |
- role=alertdialog makes screen readers read the title and body as soon as it opens.
- Focus is trapped inside the dialog and returns to the trigger when it closes.
- Don't rely on red alone: the button text says what it does.
Do and don't
DoName the thing being deleted in the title and on the button.
Don'tAsk “Are you sure?” with OK and Cancel.
DoDo reversible actions straight away and offer Undo.
Don'tConfirm every archive, move and mark-as-read.
DoSay what else is affected: “3 approvers will be notified”.
Don'tHide the consequences behind a “Learn more” link.