Create a hold-to-confirm button with an SVG progress ring.
On mousedown:
- Drive progress 0→1 over 1.5 seconds using requestAnimationFrame + performance.now()
- Update SVG circle strokeDashoffset: CIRCUMFERENCE * (1 - progress)
- When complete: show confirmed state (checkmark, green) for 1.8 seconds, then reset
On mouseup or mouseleave (before complete):
- cancelAnimationFrame and reset progress to 0
SVG: two circles (track + progress arc), r=22, strokeDasharray=2πr
Use refs to avoid stale closure issues (doneRef, rafRef, startRef).
No library dependencies.
Paste into Claude, ChatGPT, or Cursor. Edit YOUR_STACK /
YOUR_STYLING / YOUR_CONSTRAINTS before sending.