Feature Playground

Micro-interaction · 8.2

Boop: self-reverting spring hover

Flicking a desk toy and watching it settle.

On hover, an element springs into an exaggerated transform, then springs back on its own.

4 knobs

How it actually works

Tension and friction are the two most legible physics knobs that exist. Two numbers, infinite personalities, and you feel the difference immediately rather than reasoning about it. Drop friction to 3 and the thing will not stop ringing. Push it to 40 and it never overshoots at all, which is to say it stops being a spring and becomes an ease.

A spring, integrated per frame, not an easing curve with a duration. The sourced config is tension 300, friction 10, and a timeout flips the state back so the element reverts without waiting for mouse-leave. That last part is the whole idea: it boops, it does not toggle.

The knobs, named

Tension, friction, the transform itself, and the revert timeout. Tension 300 and friction 10 are verbatim from the source.

KnobSourceWhat it teaches
Tension sourced Stiffness. The source's value is 300. High tension is a fast, tight snap.
Friction sourced Damping. The source's value is 10. Below about 6 it rings; above 30 it cannot overshoot.
Transform sourced What the spring drives. The spring does not care.
Revert timeout sourced How long before it springs back on its own. This is what makes it a boop.

sourced means the source names this parameter. ours means the source names none and the knob is our design against the mechanism. No knob here is invented and passed off as sourced.

Evidence

VERIFIED (author)

joshwcomeau.com/react/boop/. The useBoop hook, the react-spring tension 300 / friction 10 config, and the reduced-motion handling are all the author's own.

Seen on
joshwcomeau.com.
Dependencies
react-spring in the source; vanilla spring integrator here
Difficulty
trivial-to-moderate with react-spring; moderate vanilla
Performance
backfaceVisibility: hidden forces GPU-layer promotion. One spring per active element, integrated in the shared loop.
Accessibility and the floor
The author respects reduced-motion, one of the few sources in this index that does. Ours holds the element at rest under reduced motion, and the sliders still work.

Notes

Composability. The spring integrator here is the same one 11.1 uses for inertia. A spring and a lerp are the two ways anything on a page ever feels physical.

The source respects prefers-reduced-motion, which the index notes is rare enough to be worth remarking on: it is one of the very few sources in 171 entries that does. Our version loses true interruptibility compared to react-spring, which is the honest cost of doing it vanilla, and you can feel it if you boop the same element twice very fast.