Configuration
There are three ways to dial in how a spring moves: raw physics, perceptual feel, or named presets. They all produce the same kind of motion — pick whichever you think in.
Physics
Every spring is defined by three constants:
| Option | Default | Effect |
|---|---|---|
stiffness | 180 | Spring constant k. Higher = snappier. |
damping | 12 | Damping coefficient c. Higher = less oscillation. |
mass | 1 | Mass m. Higher = more sluggish. |
import { spring } from "sprungdesign";
spring({ stiffness: 320, damping: 14, mass: 1, onUpdate });The relationship between these is captured by the damping ratio ζ
(createSpring(config).zeta):
- ζ < 1 — underdamped: overshoots and oscillates (bouncy).
- ζ = 1 — critically damped: fastest approach with no overshoot.
- ζ > 1 — overdamped: slow, sluggish, no overshoot.
Feel
If you’d rather think like a designer than a physicist, use fromFeel to map
duration + bounce onto those constants:
import { fromFeel, spring } from "sprungdesign";
spring({ ...fromFeel({ duration: 0.5, bounce: 0.3 }), onUpdate });| Option | Default | Effect |
|---|---|---|
duration | 0.5 | Perceptual duration in seconds — sets the natural frequency. |
bounce | 0.2 | [-1, 1]: >0 bouncy, 0 critical (no overshoot), <0 sluggish. |
mass | 1 | Mass. |
The bounce extremes are clamped to a settling range, so ±1 stay usable
rather than degenerate.
Presets
Four named configs cover most UI needs:
import { presets, spring } from "sprungdesign";
spring({ ...presets.bouncy, onUpdate }); // gentle · bouncy · stiff · lazy| Preset | stiffness | damping | mass | Feel |
|---|---|---|---|---|
gentle | 120 | 14 | 1 | Soft, a little overshoot |
bouncy | 320 | 14 | 1 | Snappy with a clear bounce |
stiff | 420 | 40 | 1 | Fast, almost no overshoot |
lazy | 80 | 26 | 1.4 | Slow and heavy |
Settling thresholds
A spring is considered settled once it’s within both thresholds of the target, at which point it snaps exactly to the target and stops:
| Option | Default | Settles when… |
|---|---|---|
restDistance | 0.05 | ` |
restVelocity | 0.05 | ` |
Raise them for large value ranges (e.g. animating thousands of pixels) so the spring doesn’t crawl the last fraction; lower them for sub-pixel precision.
Initial velocity
Seed a spring with motion using velocity — useful for handing off from a drag
or fling gesture so the spring continues naturally:
spring({ velocity: 600, onUpdate }); // already moving at 600 units/secNext steps
- See the full option list in the API Reference.
- Apply these in React via the React guide.