Popconfirm
v1.0.18Updated 19 Oct 2026Inline confirmation popover for destructive or consequential actions. Wraps any trigger; on open shows a tone-aware icon, title, optional description, and Cancel + Confirm buttons. Async onConfirm shows a loading spinner
Preview
Live · 10 stories▸Why this is recommendedconfirmdestructivepopoverinline-dialog+3
The default, out-of-the-box Popconfirm.
- ✓Delete buttons in tables and lists
- ✓Void / cancel / archive actions
- ✓Any one-click action that needs a lightweight second look without a full Dialog
- Tone-aware icon + accent via shared tone recipes (danger default)
- Sync or async onConfirm with loading state on the confirm button
- Stays open and shows the rejection message on async error
- Focus moves to Cancel on open; Escape cancels; dismissal blocked mid-flight
- Controlled and uncontrolled open state
- side / align / sideOffset placement
- disabled prop suppresses opening entirely
- closeOnOutsideClick={false} makes an outside click no answer at all — neither confirm nor cancel — so a misplaced click cannot silently dismiss the question (fb_8ca9c11a)
- Custom icon override (or icon={null} to hide)
- i18n: labels prop overrides the Confirm/Cancel fallbacks and the async-error fallback message; merged over DEFAULT_POPCONFIRM_LABELS (confirmLabel/cancelLabel props win)
- ✕Multi-field input before confirming (use Dialog or Popover form)
- ✕Legally significant confirmations that must interrupt (use AlertDialog/Dialog)
Install
Ask your agent, or call the MCP tool directly. The resolved bundle is written into your project.
Usage
Tick variants in the left menu — each adds a tab with that variant’s real story source, the same code the preview above renders.
Props
childrenThe trigger the popconfirm wraps, rendered through Radix `asChild` — so pass exactly ONE element that forwards a ref and spreads props, e.g. a Button. There is no trigger prop: the element you wrap IS the trigger, and a second click on it closes the popconfirm without recording an answer
yestitleShort question, e.g. "Delete this invoice?"
yesdescriptionSupporting copy explaining the consequence
—toneSemantic tone; picks icon + accent (default danger)
—onConfirmSync closes immediately; async shows loading, closes on resolve, shows error on reject
—onCancelCalled on the cancel button, Escape, or an outside click — the last of those only while closeOnOutsideClick is true
—confirmLabelConfirm button label (default "Confirm")
—cancelLabelCancel button label (default "Cancel")
—disabledPrevents opening entirely
—sidePreferred side (default top)
—alignAlignment against the trigger (default center)
—sideOffsetDistance from the trigger in px (default 6)
—iconReplace the tone-derived icon. Pass `null` to drop the icon and its circle entirely; leave it undefined to keep the icon the tone chose
—openControlled open state (defaultOpen for uncontrolled)
—defaultOpenInitial open state for uncontrolled usage; ignored once `open` is provided
—onOpenChangeFires whenever the open state changes, controlled or not. It is the open/closed signal, not the answer — read `onConfirm` / `onCancel` for that. It is NOT called for a request the component refuses: opening while `disabled`, or any dismissal while an async confirm is still in flight
—closeOnOutsideClickWhether a click outside cancels (default true — the behaviour it has always had). Set false and an outside click is no answer at all: onCancel does not fire and the question stays on screen. Escape and the Cancel button are unaffected (fb_8ca9c11a)
—labelsOverride the built-in strings (i18n): Confirm/Cancel fallbacks and the async-error fallback message. Merged over DEFAULT_POPCONFIRM_LABELS
—Every tonal component shares the same tone × emphasis API, so the pair looks identical across Button, Badge, Alert and more.