Hold to confirm

Confirm a destructive action by holding, not tapping.

pnpm dlx shadcn@latest add @uiarc/hold-to-confirm
Live · keyboard ready

Atlas web app

Design team · 128 files

Active

Deleting removes the project, its files, and every shared link for the Design team.

Press and hold for 1.2 seconds to confirm. With a keyboard, hold Space or Enter.

Hold for 1.2 seconds, or hold Space

  • Destructive actions like delete or revoke where the consequence is already visible on screen.
  • Replacing a confirm dialog with a deliberate press in compact settings rows.
  • Actions that should not fire on an accidental tap on touch devices.
  • Use dialog when people need to read what will happen before confirming.
  • Use button or action-button for safe, easily undone actions.
  • Use swipe-actions for delete in touch lists.

Installation

Add Hold to confirm with the shadcn CLI, or copy the source by hand.

pnpm dlx shadcn@latest add @uiarc/hold-to-confirm

Adds the component and its local dependencies, and installs motion, lucide-react. First time? Add the @uiarc registry to components.json, or use the full URL:

example.tsx
import { HoldToConfirm } from "@/registry/components/hold-to-confirm/hold-to-confirm"; export function DeleteProject({ onDelete }: { onDelete: () => void }) {  return (    <HoldToConfirm      label="Hold to delete project"      confirmedLabel="Deleted"      duration={1500}      onConfirm={onDelete}    />  );}

Keep holding hint

example.tsx
const [holding, setHolding] = useState(false); <HoldToConfirm label="Hold to revoke key" onConfirm={revoke} onHoldChange={setHolding} /><p aria-hidden="true">{holding ? "Keep holding" : ""}</p>

HoldToConfirm

A button that commits only after a press is held, with a fill that tracks the hold and rewinds on early release.

PropTypeDefaultDescription
labelRequiredstring–Instruction and action, such as "Hold to delete project".
onConfirmRequired() => void–Called once when the hold completes.
confirmedLabelstring"Done"Label after the hold completes.
durationnumber1200Hold length in milliseconds.
iconReactNode<Trash2 />Leading icon. Replaced by a drawn check when done.
tone"danger" | "neutral""danger"Fill color.
confirmedboolean–Controls the done state. Set back to false to reset; leave undefined to let the button manage it.
onHoldChange(holding: boolean) => void–Reports when a hold starts and ends, for hints like "Keep holding".
...propsButtonHTMLAttributes<HTMLButtonElement>–Forwarded to the button, except children and onClick.
SpaceorEnter (hold)
Fills the button; releasing early rewinds it.
Tab away
Cancels an active hold.
  • aria-describedby points to a hidden hint: "Press and hold for N seconds to confirm. With a keyboard, hold Space or Enter."
  • aria-label tracks the visible label; a role="status" region announces confirmedLabel.
  • Once done the button sets aria-disabled; the text is drawn twice so it changes color exactly at the fill edge.
  • The fill advances on a linear timeline while held, rewinds on a smooth spring when released, and resumes from where it was on a quick re-press.
  • The button presses to about 0.97; on completion the label morphs, the width springs, and a check draws itself in. Touch devices get a short vibration.
  • Reduced motion drops the press scale and rewind spring and swaps label and icon with a fade; the fill still tracks the hold.
  • Uses pointer events with capture, so mouse, pen, and touch holds all work; sliding more than 24px off the button cancels the hold.
  • Touch holds trigger a short vibration on completion where the device supports it.
  • Keyboard users hold Space or Enter, and a hidden hint explains the duration.
  • The fill runs on a single linear motion animation, not a React state update per frame.
  • The label is drawn twice to change color at the fill edge; a ResizeObserver handles the width spring on completion.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Use for destructive or hard-to-undo actions when the consequence is already visible on screen. Use dialog when people need to read what will happen first.
  • Write the label as an instruction ("Hold to …"); pass confirmed to reset it after an undo or a failed request.
  • Pair with onHoldChange to show a nearby hint while the press is held.

The full library index for assistants is at /llms.txt.