Asks one question before an action that can't be undone, such as deleting an API key.
Live React portVue source: WildConfirmDialog.vueReact component: WConfirmDialog
Try it
Set the label to OK to see how little the button says. Press Delete key to reopen it.
Delete this API key?
It is removed permanently.
Confirm label
Tone
Consequence
<WConfirmDialog
open={open}
title="Delete this API key?"
confirmLabel="Delete key"
onConfirm={deleteKey}
onCancel={() => setOpen(false)}
>
It is removed permanently.
</WConfirmDialog>
When to use
Use it before an action that deletes data or can’t be undone.
Use it when an action affects more than the thing in front of the person, such as anything that uses an API key.
Use it, in the primary tone, before a reversible action with wide effects, such as pausing an automation.
Don’t use it
For routine actions that are quick to undo. Run them, and confirm with a toast.
Destructive is the default. Use primary when nothing is lost but the effect is wide, such as pausing an automation. Add a consequence panel when the action reaches beyond the thing itself.
Cancel this invite?
It is removed permanently.
<WConfirmDialog open={open} title="Cancel this invite?" confirmLabel="Cancel invite" cancelLabel="Keep invite" onConfirm={cancelInvite} onCancel={() => setOpen(false)}
>
It is removed permanently.
</WConfirmDialog>
The confirm sits on the right, where the primary always sits. Cancel can name what it keeps.
Delete this API key?
It is removed permanently.
Anything using this key can no longer reach the API.
<WConfirmDialog open={open} title="Delete this API key?" confirmLabel="Delete key" consequence="Anything using this key can no longer reach the API." onConfirm={deleteKey} onCancel={() => setOpen(false)}
>
It is removed permanently.
</WConfirmDialog>
Pause this automation?
It stops running until you turn it back on.
<WConfirmDialog open={open} title="Pause this automation?" confirmLabel="Pause automation" tone="primary" onConfirm={pauseAutomation} onCancel={() => setOpen(false)}
>
It stops running until you turn it back on.
</WConfirmDialog>
Content
Ask the question in the title, naming the thing: “Delete this API key?”
Say in the body what is lost and what isn’t.
Name the consequence on the button: “Delete key”, “Cancel invite”. People who skim the body still read the button.
Name what else breaks in the consequence panel, with a number where there is one.
Name what Cancel keeps when “Cancel” would be ambiguous: “Keep invite”.
Don’t use it
OK, Yes or Confirm on the button. They don’t say what happens.
Accessibility
It opens as an alert dialog, named by its title and described by its body and consequence. Focus lands on Cancel, so a double Enter can’t delete anything, and returns to the trigger on close.
Key
What it does
Tab / Shift+Tab
Moves between the buttons, staying inside the dialog.
Enter / Space
Presses the focused button.
Esc
Cancels and closes.
Props
Prop
Type
Default
Description
open
boolean
—
Shows the dialog.
title
ReactNode
—
The question, naming the thing affected.
children
ReactNode
—
What is lost, in a sentence or two.
confirmLabel
string
—
Verb and object: Delete key. Required.
cancelLabel
string
'Cancel'
The safe action.
tone
'destructive' | 'primary'
'destructive'
Primary when nothing is lost, such as a pause.
consequence
ReactNode
—
Warning panel for knock-on effects.
loading
boolean
false
Spinner on the confirm while the action runs.
onConfirm
() => void
—
Runs the action.
onCancel
() => void
—
Cancel, Esc, the close button or the scrim.
closeOnOverlay
boolean
true
Whether a scrim click cancels.
contained
boolean
false
Fills the nearest positioned parent instead of the viewport.