There’s a category of software that people describe as “feeling fast” even when benchmark numbers say otherwise. There’s a category that people describe as “feeling polished” before they can articulate why. Both categories are built by engineers who understand micro-interactions.
What Makes an Interaction “Micro”?
Micro-interactions are the feedback loops that acknowledge user input. The button that compresses slightly on press. The form field that gently shakes on validation error. The checkbox that doesn’t just toggle — it springs.
They’re “micro” because they’re small. But small doesn’t mean unimportant. They’re often the primary carrier of your product’s personality.
Physics-Based Animation: Why Springs Work
The worst animations use linear or bezier timing. They look mechanical because they are — they have no physical analogue.
Springs work because they model real-world deceleration:
const springConfig = {
damping: 15, // How quickly oscillation dies out
stiffness: 150, // How strong the spring force is
mass: 0.1, // Simulated mass of the moving object
};
const x = useSpring(0, springConfig);
Low damping + high stiffness = bouncy, playful feel. High damping + low stiffness = smooth, professional feel.
The key insight: when users drag an element and release it, a spring “catches” it naturally. A bezier curve has to arbitrarily choose where the element ends up.
The Magnetic Button Pattern
One of the most effective micro-interactions for clickable elements: the element slightly moves toward the cursor as the user approaches.
const handleMouseMove = (e: React.MouseEvent) => {
const rect = ref.current!.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const intensity = 0.4;
x.set((e.clientX - centerX) * intensity);
y.set((e.clientY - centerY) * intensity);
};
The subtle physics signal: the element wants to be clicked. It’s reaching toward you.
Staggered Reveals
When a list of items appears, they shouldn’t all appear simultaneously. Staggered entrance creates a sense that the items are being assembled, not just appearing.
<motion.ul
variants={{
visible: { transition: { staggerChildren: 0.05 } }
}}
initial="hidden"
animate="visible"
>
{items.map(item => (
<motion.li
key={item.id}
variants={{
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 }
}}
/>
))}
</motion.ul>
The 50ms stagger is almost invisible to conscious perception but dramatically changes the feeling of the page loading.
The Reduced Motion Contract
Every animation you ship needs a prefers-reduced-motion fallback. This isn’t optional — it’s an accessibility requirement. Some users experience motion sickness from parallax effects and spring animations.
const prefersReducedMotion = useReducedMotion();
// Don't just hide animations — provide a suitable alternative
if (prefersReducedMotion) {
return <StaticVersion />;
}
The test: everything your application does should be possible without animations. Animations are enhancement, not function.
The 100ms Rule
Interactions that take longer than 100ms to provide feedback feel broken. The feedback doesn’t have to be the final state — it just has to acknowledge that something is happening.
Button press → immediate visual compression, then the action executes. Form submit → immediate loading state, then the result.
The loading state isn’t failure. The silence is failure.
Building a Vocabulary
The best interactive products have consistent animation vocabularies. Enter animations use the same spring. Error states use the same shake. Success states use the same color transition.
Inconsistency in micro-interactions is like inconsistency in typography — it creates a diffuse sense of “something’s off” that users can feel but can’t name.
Document your spring configs. Put them in your design tokens. Treat them with the same seriousness as your color palette.
Related Reading
Building a Custom React Renderer from Scratch
How React-reconciler works, why you'd ever want to build your own renderer, and a working implementation that renders to a terminal canvas.
EngineeringDesign Systems That Actually Scale
Technical decisions that distinguish design systems used by 5 engineers from those used by 50. Token architecture, component API design, and the organizational structures that make or break adoption.