A round hold-to-fire button with a tick-marked progress ring that winds up while held and unwinds faster when released early. The button rumbles harder as it charges and bursts into a check when it fires.
npx shadcn@latest add https://hyperblur.dev/r/button-hold-ring.jsonWorks in any React project set up with the shadcn CLI. The file lands in components/hyperblur/button-hold-ring.tsx.
import { ButtonHoldRing } from "@/components/hyperblur/button-hold-ring"
<ButtonHoldRing label="Hold to go live" onFire={() => startStream()} />| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | "Hold to go live" | Title shown beside the button in the idle state. |
| hint | string | "Hold for 1.2 seconds" | Helper line under the title. |
| holdingLabel | string | "Keep holding" | Title while the ring is charging, shown with a live countdown. |
| firedLabel | string | "You're live" | Title after the action fires. |
| firedHint | string | "Streaming now" | Helper line after the action fires, with a pulsing dot. |
| icon | ReactNode | broadcast icon | Icon inside the button. |
| duration | number | 1200 | Milliseconds of holding needed to fire. |
| resetAfter | number | 2200 | Milliseconds before the fired state resets to idle. |
| size | number | 64 | Button diameter in pixels. The ring sits 8px outside it. |
| accent | string | "#ff4d5e" | Ring, charge glow and fired color. |
| onFire | () => void | undefined | Called once when the ring completes. |
| onProgress | (progress: number) => void | undefined | Called every frame with the charge from 0 to 1. |
| disabled | boolean | false | Disables interaction and dims the control. |