Hold to confirm
Confirm a destructive action by holding, not tapping.
pnpm dlx shadcn@latest add @uiarc/hold-to-confirmLive · keyboard ready
Atlas web app
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-confirmAdds 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.