A hold-to-confirm button for actions that deserve a second of thought: pressing and holding fills it from the left, the label flipping color as the fill passes under it, and letting go early rewinds the fill smoothly. When the hold completes a check draws itself in, the label changes, a short vibration marks it where supported, and the button resets on its own or stays confirmed. Works with the pointer and by holding Space or Enter; screen readers, which cannot hold, confirm with a single activation unless that is turned off. Duration, labels, icon, destructive or default tone, three sizes, and controlled or uncontrolled confirmed state.
The import and the props worth knowing about, in one place.
import { HoldConfirm } from "@/components/beste/component/hold-confirm";
import { Trash2 } from "lucide-react";
<HoldConfirm
label="Delete the album"
holdingLabel="Keep holding"
confirmedLabel="Album deleted"
icon={Trash2}
tone="destructive"
onConfirm={() => console.log("Deleted")}
/>
<HoldConfirm
label="Publish to every store"
duration={2000} // a longer hold for a bigger commitment
resetAfter={null} // stay confirmed
size="lg"
/>Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.
| Press and hold | Fills the button. Letting go early rewinds it. |
|---|---|
| Hold Space or Enter | The same hold from the keyboard; releasing the key lets go. |
| Activate with a screen reader | Confirms at once while Accessible fallback is on, since a hold cannot be performed. |
Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
label* | string | — | |
holdingLabel | string | — | Shown while the button is held. Defaults to `label`. |
confirmedLabel | string | — | Shown once the hold completes. |
icon | React.ComponentType<{ className?: string }> | React.ReactNode | — | A lucide icon component, or any node, before the label. |
duration | number | — | How long the button must be held, in ms. |
onConfirm | () => void | — | |
onHoldStart | () => void | — | |
onHoldCancel | () => void | — | Released before the hold completed. |
confirmed | boolean | — | Whether the button shows its confirmed state. Pair with `onConfirmedChange` to control it. |
defaultConfirmed | boolean | — | |
onConfirmedChange | (confirmed: boolean) => void | — | |
resetAfter | number | null | — | Ms before the confirmed state resets on its own. `null` keeps it. |
hint | string | — | The description read after the label. |
accessibleFallback | boolean | — | Screen readers that activate the button without a key press confirm at once instead of being locked out. |
disabled | boolean | — | |
tone | "default" | "destructive" | — | |
size | "sm" | "default" | "lg" | — | |
className | string | — |