A hold to confirm button that fills while held and fires only when the hold completes.
Adds the component and everything it depends on to your project.
npx shadcn add https://ui.beste.co/component/r-base/button14New here? Read the installation guide.
The import and the props worth knowing about, in one place.
import { Button14 } from "@/components/beste/component/button14";
import { LogOut } from "lucide-react";
// onConfirm fires only after the button is held for holdDuration ms.
// Releasing early cancels and snaps the fill back.
<Button14
label="Hold to delete"
confirmLabel="Deleted" // shown once the hold completes
onConfirm={() => console.log("deleted")}
/>
<Button14
label="Hold to sign out"
confirmLabel="Signed out"
icon={LogOut} // idle icon (default: Trash2)
tone="dark" // "destructive" (default) | "dark" | "primary"
rounded="md" // "full" (default) | "lg" | "md" | "none"
holdDuration={800} // ms the button must be held
resetDelay={0} // 0 keeps the confirmed state (no auto-reset)
onConfirm={() => console.log("signed out")}
/>Turn the props on the right; the snippet under them is what you would write to get what you see.
import { Button14 } from "@/components/beste/component/button14";
<Button14
label="Hold to delete"
confirmLabel="Deleted"
/>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 | The fill crosses the button over `holdDuration`; only when it lands does `onConfirm` run. |
|---|---|
| Release early | The fill runs back and nothing is confirmed. That is the whole point of the control. |
| Space / Enter held | Holds the same way, so the keyboard is not offered a shortcut past the pause. |
Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
label* | string | — | Idle label (e.g. "Hold to delete") |
confirmLabel | string | — | Label shown once the hold completes |
holdDuration | number | — | How long the button must be held, in ms |
resetDelay | number | — | How long the confirmed state is shown before resetting, in ms; 0 disables the reset |
icon | LucideIcon | — | Leading icon in the idle state (defaults to Trash2) |
tone | "destructive" | "dark" | "primary" | — | Fill tone: destructive (default), dark, or primary |
rounded | "full" | "lg" | "md" | "none" | — | Corner radius (defaults to full) |
onConfirm | () => void | — | Called once, when the hold completes |
className | string | — | Additional classes merged onto the button |
An async loading button that shows a spinner and disables itself while a promise resolves.
A video play button with a circular play seal, label, and duration for showreels and product demos.
An expanding icon button that reveals its label on hover or focus for compact layouts.