Hold To Commit Button
A destructive action that requires sustained pressure, with a ring that fills on an ease-in curve.
- Category
- Components
- Added
- 2026-09-21
- Deps
- 1
- Updated
- 2026-09-21
This is a viberdy Pro component
The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.
Props
"use client";
import { useCallback, useRef, useState } from "react";
import { Check, Trash2 } from "lucide-react";
type Phase = "idle" | "holding" | "done";
export function HoldToCommitButton({
label = "Hold to delete",
duration = 1400,
danger = "#e5484d",
onCommit,
}: {
label?: string;
duration?: number;
danger?: string;
onCommit?: () => void;
}) {
// ---------------------------------------------------------------
// Full source available with a viberdy Pro subscription.
// https://viberdy.dev/pricing
// ---------------------------------------------------------------
}About this component
A confirmation dialog asks a question the user answers by reflex; a hold asks for sustained intent, which is much harder to give accidentally. The timing curve is the whole product here. Linear feels punitive because the user is just waiting out a timer, and ease-out feels finished well before it is, so people release early and nothing happens — the worst possible outcome for a control whose entire purpose is deliberate commitment. Ease-in is correct: slow to start, fast to finish, so there is a clear moment of crossing and the last third pulls the user through it. The ring is a conic gradient masked to the border, which is the cheapest exact arc available and stays correct at any size without SVG or dasharray arithmetic, and pressure is sold through compression, a deepening inset shadow and tightening letter-spacing rather than a colour change. The genuinely hard part is aborting. A hold can end in far more ways than it begins — the pointer released outside the element, a cancelled pointer, the window losing focus, a context menu — and a ring that keeps filling after the user has switched away before firing a destructive action is the failure that matters. Pointer capture covers two of those cases and the rest are handled explicitly.
Curator’s note
The ease-in curve is the entire design. Everything else is dressing on a decision the timing already made.
Pairs well with
Matched on shared tags and category — the entries most likely to be used alongside this one.
Magnetic Button
componentsA button whose label leans toward the cursor with a springy pull.
Stroke Draw Button
componentsA button whose outline draws itself around the shape on hover, at any size.
Async Action Button
componentsA button that survives a real round trip — a minimum pending duration, a width that never twitches, aria-disabled instead of disabled.