ConfirmDialog
Destructive confirmation armed by press-and-hold.
ConfirmDialog makes destructive actions deliberate: a modal that asks in plain language, and a confirm action you have to hold. Press and a destructive fill sweeps across the button for exactly holdMs — linear, because it’s progress, not decoration — while the button itself trembles harder as the fill closes in (shake) — flat for most of the hold, then surging near the end. The fill carries its own light copy of the label behind a clip-path, so the sweep edge crosses the letterforms — light behind it, destructive ahead of it — instead of the whole label flipping color mid-hold. Release early and it springs back, no harm done; hold to the end and the action arms once and the dialog closes. Holding Space or Enter works the same way. CheckpointTimeline pops it before every restore.
Install
npx shadcn@latest add https://ui.neon.com/r/confirm-dialog.json
Usage
import { ConfirmDialog } from "@/components/neon-ui/confirm-dialog";
<ConfirmDialog
open={open}
onOpenChange={setOpen}
onConfirm={() => deleteApp(app.id)}
title="Delete this app?"
description="acme-crm and its Neon project are deleted immediately. This cannot be undone."
confirmLabel="Hold to delete"
/>;
Props
openboolean
Controlled open state.
booleanonOpenChange(open: boolean) => void
(open: boolean) => voidonConfirm() => void
Runs once when the hold completes; the dialog closes itself.
() => voidtitlestring
One line naming the action.
stringdescription?ReactNode
What happens and what it costs — say it plainly.
ReactNodeconfirmLabel?string
string"Hold to confirm"cancelLabel?string
string"Cancel"shake?boolean
The hold trembles as it approaches commitment; off under prefers-reduced-motion.
booleantrueholdMs?number
How long the hold takes to arm.
number1200Accessibility
- Base UI dialog semantics: focus trap,
aria-modal, labelled by the title, described by the description; Escape and the cancel action both dismiss. - The hold works from the keyboard — hold Space or Enter; key repeat is ignored, releasing cancels.
- The progress fill is decorative (
aria-hidden); the hold requirement is stated in the visible label. - Closing mid-hold clears the timer — the action can never fire after dismissal.