Skip to content
Template Empire
Browse components

Hold to Confirm Button

A free hold to confirm button React component with cancellable progress, keyboard parity and two visual directions.

Contractor payouts

Release the July payout run

US$18,206.40 goes out to 143 contractors the moment the run clears. A released run cannot be recalled.

Approved by A. Osei and R. Vance. Settles in one business day.

Customise

1200ms
184px
48px

Code

<BtnHoldConfirm />

Hold to Confirm Button is a free button component for Next.js and React, styled with Tailwind and animated with Motion. It makes deliberate actions safer by requiring a continuous press for a bounded duration, then calls onConfirm once and shows a clear success state before resetting.

Pointer capture keeps a mouse, pen or touch attempt deterministic even when it moves away from the control. Space and Enter provide the same hold and cancellation behaviour for keyboard users, while early release, pointer cancellation, lost capture, blur or Escape always restores the resting state. Reduced motion preserves the full hold requirement with fixed geometry, a static brand surface and textual feedback instead of continuous travel.

Install

Add the @te registry to your components.json once:

{
  "registries": {
    "@te": "https://templateempire.io/r/{name}.json"
  }
}

Then install the component:

npx shadcn@latest add @te/btn-hold-confirm

Usage

import { BtnHoldConfirm } from "@/components/btn-hold-confirm";

export default function PublishControl() {
  return (
    <BtnHoldConfirm
      label="Hold to publish"
      holdingLabel="Keep holding"
      successLabel="Published"
      onConfirm={() => {
        console.log("Publish confirmed");
      }}
    />
  );
}

Props

PropTypeDefaultDescription
labelstring"Hold to confirm"Resting accessible and visible label.
holdingLabelstring"Keep holding"Visible label while an attempt is active.
successLabelstring"Confirmed"Visible completion label and polite announcement.
holdDurationnumber1200Completion duration in milliseconds, clamped to 600-3000.
widthnumber184Button width in CSS pixels, clamped to 144-280.
heightnumber48Button height in CSS pixels, clamped to 40-64.
progressDirection"left-to-right" | "radial""left-to-right"Visual progress treatment only.
disabledbooleanfalseUses native button disabled behaviour.
onConfirm() => voidundefinedCalled exactly once after a completed hold.
classNamestringundefinedAdditional classes merged onto the button.

Customisation

Hold to Confirm Button exposes two Tier 3 CSS variables. The fill token colours the resting and holding surface, and the success token colours the completed surface; progress is drawn as a theme-derived wash over the fill, so it needs no token of its own. Geometry and timing remain available through props:

<div
  style={{
    "--hold-confirm-fill": "var(--ring)",
    "--hold-confirm-success": "var(--primary)",
  }}
>
  <BtnHoldConfirm
    holdDuration={1600}
    width={216}
    height={52}
    progressDirection="radial"
  />
</div>

Frequently asked questions

Is Hold to Confirm Button free for commercial use?
Yes. Hold to Confirm Button is MIT licensed, so you can use it in personal and commercial projects without attribution.
Is the hold interaction accessible and performant?
Yes. It is one native button with a stable accessible name, native disabled semantics, a visible focus ring and a polite live region for cancellation and completion. Pointer and keyboard users receive the same bounded interaction. The animated progress uses transform scaling or SVG pathLength rather than layout properties, and reduced motion keeps the hold timing while replacing travel with static textual feedback.
How can I customise the hold duration and progress style?
Set holdDuration between 600 and 3000 milliseconds, choose left-to-right or radial with progressDirection, and adjust width and height within their documented bounds. Use the two hold-confirm CSS variables to retheme the brand fill and the success surface without changing the component source.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with this interaction system throughout. Browse the paid templates that pair with these free components.Explore Template Empire templates