React Spring Mouse Tracking Example: Building Spring-Based Cursor Animations with Emil Kowalski's Skills
Use @react-spring/web with useSpring() and animated.div to create a physics-based cursor follower where tension (170) and friction (26) control the spring stiffness and damping.
The skills repository by Emil Kowalski is a curated collection of AI-assisted UI design workflows. Each skill is a markdown-based instruction set that guides agents through opinionated animation and prototyping tasks. This article walks through applying the prototype skill to generate a React Spring mouse tracking component—no hand-tuned keyframes required.
What Is the Skills Repository?
The repository at emilkowalski/skills contains no executable code. Instead, it stores skill definitions: plain-text .md files with front matter (name, description) and step-by-step workflows for AI agents.
According to the root README.md, the project exists because "Agents don't have great taste" and need structured guidance to produce usable UI artifacts【1†L29-L38】.
Key locations in the repo:
skills/animate/SKILL.md— Full animation construction workflowskills/prototype/SKILL.md— Multi-variant prototyping with visual pickerskills/pick-ui-library/SKILL.md— Library selection guidelinesskills/animation-vocabulary/SKILL.md— Standardized motion terminology
The Prototype Skill Workflow for React Spring Mouse Tracking
The prototype skill in skills/prototype/SKILL.md prescribes a six-phase process for generating UI variants【3†L25-L48】. Here's how it applies to our React Spring mouse tracking example.
Phase 1: Scope Definition
Define a single, focused UI element. For mouse tracking, this is a circular cursor follower with spring physics.
Phase 2: Stack Reconnaissance
Identify the toolchain. The prototype skill directs agents to select proven libraries over hand-rolled solutions. We choose:
- React — Component framework
- @react-spring/web — Physics-based animation (the
useSpringhook andanimatedcomponents)
Phase 3: Variant Generation
Generate 2–3 genuinely different implementations. The baseline below uses default spring physics; variants could adjust tension/friction or add visual effects like trails.
Phase 4: Picker Harness
The skill includes a PICKER.md file with markup for a live variant switcher. In production, agents copy this verbatim to render all variants behind a toggle.
Phase 5: Verification
Ensure the snippet runs without console errors in React 17+.
Phase 6: Promotion
Once selected, move the component into the main codebase and delete prototype files.
Complete React Spring Mouse Tracking Code
Here's the production-ready implementation following the prototype skill's structure:
import { useSpring, animated } from '@react-spring/web';
import { useEffect } from 'react';
export default function SpringMouseTracker() {
const [{ x, y }, api] = useSpring(() => ({ x: 0, y: 0 }));
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
api.start({
x: e.clientX,
y: e.clientY,
config: { tension: 170, friction: 26 },
});
};
window.addEventListener('mousemove', handleMouseMove);
return () => window.removeEventListener('mousemove', handleMouseMove);
}, [api]);
return (
<animated.div
style={{
position: 'fixed',
left: 0,
top: 0,
width: 20,
height: 20,
borderRadius: '50%',
background: 'rgba(0, 150, 255, 0.6)',
pointerEvents: 'none',
transform: x
.to((xVal) => `translate3d(${xVal - 10}px, ${y.get() - 10}px, 0)`),
}}
/>
);
}
Key Implementation Details
| Aspect | Implementation |
|---|---|
| Spring initialization | useSpring(() => ({ x: 0, y: 0 })) returns [values, api] |
| Physics config | tension: 170, friction: 26 — balanced snappiness with natural decay |
| Event handling | Global mousemove listener updates spring target via api.start() |
| Performance | translate3d GPU acceleration; pointerEvents: 'none' prevents interaction blocking |
| Cleanup | useEffect cleanup removes listener to prevent memory leaks |
Understanding the Spring Physics Parameters
The config object in @react-spring/web controls motion behavior:
- Tension (default 170) — Higher values create stiffer, faster springs. Lower values feel loose and heavy.
- Friction (default 26) — Higher values increase damping, reducing oscillation. Lower values cause more bounce.
For React Spring mouse tracking, 170/26 provides responsive cursor following without excessive wobble. For a "heavier" feel, try tension: 120, friction: 30. For elastic overshoot, reduce friction to friction: 10.
Alternative Variants for the Picker
The prototype skill encourages multiple implementations. Consider these variants:
Snappy variant (tension: 300, friction: 30) — Near-instant cursor lock with minimal overshoot.
Liquid variant (tension: 50, friction: 20) — Slow, dreamy follow with visible lag.
Trail variant — Multiple animated.div elements with staggered spring targets creating a ribbon effect.
Applying the Animate Skill for Refinement
Once the prototype is selected, the animate skill from skills/animate/SKILL.md can refine the motion. Its workflow includes:
- Gate — Verify animation is necessary (yes: provides feedback)
- Purpose — Clarify the intent (cursor presence indicator)
- Tool selection — Confirm
@react-spring/webvs. CSS transitions - Properties — Position (
x,y) vs. opacity, scale - Easing — Spring physics vs. cubic-bezier
- Duration — Physics-derived (natural) vs. fixed ms
- Exit — Add cleanup animation on unmount
The skill's decision tree prevents agents from defaulting to arbitrary durations or mismatched easing curves【2†L1-L4】.
Using the Skills CLI
Install and invoke skills directly:
# One-time installation
npx skills@latest add emilkowalski/skills
# Generate a React Spring mouse tracking prototype
skills prototype "Build a spring-based mouse follower in React with 3 physics variants"
The CLI reads skills/prototype/SKILL.md, executes its six-phase workflow, and returns the component code plus picker harness.
Summary
- The skills repository encodes UI design workflows as markdown instruction sets for AI agents.
- The prototype skill provides a structured six-phase process for generating and comparing UI variants.
- React Spring mouse tracking requires
useSpring()for physics values,api.start()for updates, andanimated.divfor GPU-accelerated rendering. - Spring
tensionandfrictionparameters directly control response speed and damping—no keyframe math needed. - The animate skill offers a secondary refinement pass with gates for necessity, tool selection, and motion quality.
Frequently Asked Questions
What makes @react-spring/web suitable for mouse tracking?
@react-spring/web uses a physics simulation rather than duration-based animation. For mouse tracking, this means the follower naturally accelerates and decelerates based on cursor velocity, producing organic motion that CSS transitions cannot replicate. The useSpring hook accepts new targets via api.start() without interrupting in-flight animation, ensuring smooth handoffs between rapid cursor movements.
How do I prevent the React Spring mouse tracker from lagging behind?
Lag is intentional physics behavior—it's the spring's natural response time. To reduce perceived lag, increase tension (stiffness) or decrease friction (damping). For instant following, set immediate: true in api.start(), though this defeats the spring purpose. Consider whether the lag serves your UX goal: it creates visual weight and can reduce cognitive load by smoothing erratic cursor movements.
Can I track mouse position without adding a global event listener?
Yes, but with trade-offs. You could attach onMouseMove to a parent container, limiting tracking to that element. However, position: fixed overlay cursors typically need window events. Ensure cleanup in the useEffect return function to prevent memory leaks when the component unmounts—this is explicitly checked in the animate skill's "Verify" phase.
Where does the skills repository store its animation guidelines?
All guidelines live in skills/animate/SKILL.md (core workflow) and skills/animation-vocabulary/SKILL.md (terminology standards). The animate skill references these to enforce consistent decision-making: gates prevent unnecessary motion, the tool selection step mandates spring or CSS appropriately, and the properties section restricts animatable attributes to performant choices (transform, opacity) rather than layout triggers.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →