Skip to content
Neon UI
Esc
navigateopen⌘Jpreview
On this page

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

PropType
openboolean

Controlled open state.

Typeboolean
onOpenChange(open: boolean) => void
Type(open: boolean) => void
onConfirm() => void

Runs once when the hold completes; the dialog closes itself.

Type() => void
titlestring

One line naming the action.

Typestring
description?ReactNode

What happens and what it costs — say it plainly.

TypeReactNode
confirmLabel?string
Typestring
Default"Hold to confirm"
cancelLabel?string
Typestring
Default"Cancel"
shake?boolean

The hold trembles as it approaches commitment; off under prefers-reduced-motion.

Typeboolean
Defaulttrue
holdMs?number

How long the hold takes to arm.

Typenumber
Default1200

Accessibility

  • 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.