The ring is driven by the clock, not by React re-renders. A setInterval ticks once a second and retriggers withTiming on the ring's shared progress value over exactly one second, so the stroke visibly drains at a steady rate instead of snapping to a new position on each whole-second update.
Easing.linear, never a spring or an ease curve, on purpose. A countdown communicates a constant rate of time passing, easing the depletion in or out would make equal seconds look like they take unequal time.
A ref tracks the actual remaining value, not just React state. The interval reads and writes a ref directly and only calls setRemaining to trigger a re-render of the on-screen digits, which sidesteps stale closures and double-firing side effects under React's dev-mode double invocation.
onComplete is read through a ref, not a dependency. The timer effect only restarts when seconds or autoStart actually change, not every time a caller passes a fresh inline function, so a parent re-render mid-countdown doesn't silently reset the clock.
The haptic and onComplete fire exactly once, guarded by a completion ref, the instant remaining reaches 0, and the interval is cleared immediately after.