Skip to main content

The problem

A user is about to do something that destroys work: delete a campaign, discard unsaved edits, remove a team member, cancel a running job. Get this wrong in one direction and people lose work they cannot recover. Get it wrong in the other and every routine action grows a modal that users learn to dismiss without reading — which destroys the protection for the cases that actually needed it. The confirmation dialog is not the pattern. The pattern is deciding whether to confirm at all.

Decide first: undo, or confirm?

Undo beats confirmation whenever it is achievable. A confirmation taxes every user every time, including the overwhelming majority who meant to do it. Undo taxes only the user who made a mistake. Building soft-delete so undo is possible is nearly always the better investment over adding a dialog.

Vocabulary

When this applies

  • The action is not reversible by the user without contacting support.
  • The action affects objects other people depend on — shared reports, live routing, team access.
  • The action stops something currently running or generating revenue.

When it doesn’t

Structure

The destructive action is never the contained Button. Weight is an invitation. The interface should be easy to escape and deliberate to commit. Severity is carried by the copy and the friction, not by making the dangerous control the most attractive one.
A cascade adds one line to the body — never a second structure. When the object being deleted has dependents, the body states what else is affected, alongside the object’s own consequence:

Three tiers of friction

Match friction to consequence. Using tier 3 everywhere is the same failure as using tier 1 everywhere — it just takes longer to show up.
1

Tier 1 — Undo. No dialog.

Reversible in-session. Perform the action, show a Toast with an Undo action for at least 10 seconds.Removing a filter, archiving a draft, deleting a row from an unsaved table.
2

Tier 2 — Dialog naming the object.

Not user-reversible, recoverable by support. Dialog states the object by name and the consequence in outcomes. Confirm button restates the action.Deleting a saved report, removing a team member, deleting a campaign with history.
3

Tier 3 — Typed confirmation.

Unrecoverable, or affects live traffic, billing, or other people’s work. The user types the object’s name to enable the confirm button.Deleting a workspace, revoking an API key in production, cancelling a running job.
Typed confirmation works because it defeats muscle memory. Its power comes entirely from being rare. Use it in more than a handful of places and users learn to copy-paste, at which point it is friction with no protection.

Behavior

Constraints

Constraints Titan should enforce

Destructive confirmation: open issues

Constraints Titan should enforce for Destructive confirmation.

Content

Do not apologize and do not soften. “We’re sorry, but this will permanently remove…” adds words at the exact moment the user should be reading carefully. State the consequence plainly and stop. Never use “Are you sure?” It asks about the user’s confidence when the useful question is about the outcome. Someone who is sure they selected the right row, but didn’t, answers “yes” correctly and still loses their work. Naming the object is what catches the error.

Accessibility

  • Dialog uses role="dialog" with aria-modal="true"; title is referenced by aria-labelledby.
  • Focus is trapped for the dialog’s lifetime and returns to the triggering control on close.
  • Initial focus lands on Cancel, so a reflex Enter on an unfamiliar dialog lands on the safe outcome.
  • Escape always closes without acting.
  • The consequence text must be in the accessible description, not conveyed by an icon or by red text alone — color is never the only carrier of meaning.
  • Typed confirmation inputs need a visible label stating exactly what to type; do not rely on placeholder text, which disappears on focus.

Variations

Anti-patterns

Confirming everything. The most common failure. Every confirmation reduces the attention paid to the next one. A product where deleting a filter and deleting a workspace both open a dialog has taught users that dialogs are noise. The scary dialog. Red header, warning triangle, contained red button. It reads as severe and behaves as an invitation — the most prominent, most attractive control on screen is the destructive one. Users click the biggest button. “Are you sure?” with Yes/No. Ambiguous at the moment of commitment, and it tests the wrong thing — the user’s confidence, not the outcome they’re about to cause. Delete with no undo and no confirmation. Occasionally shipped on the reasoning that the action is “obviously intentional.” Mis-clicks are not intentional, and neither is operating on the wrong row after a sort order changed underneath the user. Confirmation as a substitute for soft delete. A dialog is cheaper to build than recoverable deletion, so it gets chosen. It protects against mis-clicks and not against mistakes — the user who confidently deletes the wrong campaign passes the dialog without hesitating. Where the data matters, build the recovery. A cascade delete whose dialog only names the primary object. The reader discovers what else disappeared only after confirming. Treating “orphaned” and “deleted” as the same outcome in the dialog copy. They leave the product in different states, and the reader needs to know which one they’re choosing.

Known issues

No divergence or open decision is currently recorded specifically for Destructive confirmation. The nearest related entry is TITAN-DIALOG-01’s raw-Dialog-vs-Modal naming, inherited by composition rather than specific to this pattern.

Gaps in the current rules

  • Whether a grace-period “scheduled destructive” action (see Variations) needs its own cancellation UI beyond stating the deletion date.
  • What happens when the object being deleted was already removed by someone else between the dialog opening and the confirm press — a stricter case than a simple re-fetch resolves.
  • Whether typed confirmation’s match is case-sensitive, and whether it tolerates trailing whitespace. Neither is stated anywhere.

Why it works this way

Friction is the scarce resource this pattern spends. A dialog only protects the reader if seeing one still means something, and every dialog shown for a low-consequence action spends down the attention the next, real one needs. That’s why confirmation is reserved for what undo cannot cover, rather than the default for anything labeled “delete” — a product that confirms everything has, in practice, stopped confirming anything. Three tiers exist because friction that doesn’t match consequence fails in both directions. Tier 3’s typed confirmation only works because it is rare; using it at tier 2’s frequency would train the same click-through reflex a dialog is meant to prevent. Matching the tier to what’s actually at stake is what keeps the heaviest tier effective. CRUD overview, for how this pattern is the whole answer to CRUD’s Delete operation — there is no separate Delete page. Bulk selection, which routes into this page’s bulk-destructive variation rather than confirming per row.

Status

Exemplar page — first pass. This is a proposal for review, not established policy. The tier thresholds especially are judgment calls that should be checked against real Invoca product flows before adoption.
Last modified on September 17, 2026