Micro-interactions

Hold

A confirm that has to be earned — the ring fills while you hold, snaps shut when it commits, and empties on a different curve entirely if you let go early.

Install

bun add motion clsx tailwind-merge

Then copy 2 files into your project:

  • components/registry/hold/hold.tsx
  • lib/utils.ts

Props

PropTypeDefaultDescription
durationnumber1200How long a full press has to be held before it commits. Under about 600ms people let go by reflex; past 2s they assume it is broken.
indicator"ring" | "bar" | "fill""ring"Where the progress lives — a ring traced around the glyph, a bar under the control, or the control's own face flooding left to right.
thresholdnumber0.92Fraction of the track that counts as committed. Below 1 the last sliver closes itself, so the press lands a beat before the eye expects it — that early snap is what makes it feel decisive rather than punctual.
rewindRatenumber2.4How much faster a cancelled hold empties than it filled. At 1 it rewinds the same tape; above 2 the release reads as a spring letting go, which is the entire point of an asymmetric curve.
strokeWidthnumber3Weight of the progress track. Thin reads as instrumentation, thick reads as a toy.
holdScalenumber0.96How far the control sinks under the finger. The press feedback is doing more work here than the ring is — take it to 1 and the hold stops feeling physical.
commitScalenumber1.06Overshoot the control pops to at the instant of commit, before settling. This is the receipt.
successHoldnumber1.4How long the confirmed state stays on screen before the control re-arms itself.
accentColorstring (hex)"#a855f7"Amethyst of the filling track and the confirmed state.
trackColorstring (hex)"#2a2136"The unfilled remainder. Keep it close to the surface underneath — a high-contrast track turns the ring into a bullseye.

What It Demonstrates

Hold to confirm
A progress effect that fills up while the user holds a button.
Asymmetric easing
A curve that accelerates and decelerates at different rates. Feels more alive than a symmetric one.
Press / Tap feedback
A subtle scale-down when an element is clicked, so it feels physical.
Interruptible animation
An animation that can be smoothly redirected mid-flight instead of finishing first.
Ease-out
Starts fast, ends slow. The default for most UI and anything responding to the user.
Purposeful animation
Motion should serve a function — orient, give feedback, show relationships — not just decorate.

Related Components

Appears In