Spring Physics
typescript
1import { useSpring } from '@flint-ui/core'23function BouncyCard({ active }: { active: boolean }) {4 const style = useSpring({5 to: active6 ? { scale: 1.05, shadow: 12 }7 : { scale: 1, shadow: 2 },8 config: {9 tension: 300, // stiffness10 friction: 20, // damping11 mass: 1, // weight feel12 },13 })1415 return (16 <div17 style={{18 transform: `scale(${style.scale})`,19 boxShadow: `0 ${style.shadow}px ${style.shadow * 2}px rgba(0,0,0,0.1)`,20 }}21 >22 <Card>Hover me</Card>23 </div>24 )25}2627// Preset spring configs28import { springPresets } from '@flint-ui/core'29// springPresets.gentle — { tension: 120, friction: 14 }30// springPresets.wobbly — { tension: 180, friction: 12 }31// springPresets.stiff — { tension: 400, friction: 30 }32// springPresets.molasses — { tension: 60, friction: 26 }
Spring-based animations with configurable tension, friction, and mass
Overview
Spring physics create natural-feeling animations that respond to velocity and mass rather than fixed durations. Flint UI's animation utilities use spring dynamics for transitions that feel alive.
Why Springs Over Duration
CSS transitions use fixed timing functions (ease, linear, cubic-bezier). They always take the same amount of time regardless of distance. Springs adapt — a small change feels quick, a large change feels weighty.
typescript
1import { useSpring, animated } from '@flint-ui/motion'23function SpringButton() {4 const [pressed, setPressed] = useState(false)56 const style = useSpring({7 scale: pressed ? 0.95 : 1,8 config: { tension: 300, friction: 10 }9 })1011 return (12 <animated.button13 style={style}14 onPointerDown={() => setPressed(true)}15 onPointerUp={() => setPressed(false)}16 >17 Press me18 </animated.button>19 )20}
Spring Configuration
| Parameter | Effect | Default |
|---|---|---|
| tension | Stiffness — higher = snappier | 170 |
| friction | Damping — higher = less bounce | 26 |
| mass | Weight — higher = slower start | 1 |
Common Presets
typescript
1const presets = {2 gentle: { tension: 120, friction: 14 },3 wobbly: { tension: 180, friction: 12 },4 stiff: { tension: 210, friction: 20 },5 slow: { tension: 280, friction: 60 },6 molasses: { tension: 280, friction: 120 },7}
Reduced Motion Support
Always respect prefers-reduced-motion. Flint UI's motion utilities automatically disable springs when the user prefers reduced motion.
typescript
1const style = useSpring({2 opacity: visible ? 1 : 0,3 transform: visible ? 'translateY(0)' : 'translateY(20px)',4 config: { tension: 200, friction: 20 },5 immediate: prefersReducedMotion, // skip animation entirely6})