design-to-code
Transforms screenshots, Figma frames, mockups, design images, and live public websites into high-fidelity, responsive, accessible, production-ready frontend code. Use when asked to recreate a website, turn an image into code, match a page, clone a design, build a Figma design, make it responsive, repair visual differences, or translate a visual reference into React, Next.js, Vue, Svelte, HTML/CSS, or an existing project's stack.
Install
npx skills add https://github.com/Atharvsinh-codez/skills --skill design-to-codeMotion Playbook
Use this playbook when a build adds, matches, tunes, or removes interaction and motion. In reference reconstruction, observed motion outranks every default below. Use the defaults only where evidence is silent.
Contents
- Should it animate
- Pick the tool
- Pick the properties
- Easing, duration, and springs
- Interruption, origin, and exit
- Gestures
- Reduced motion and pointer gating
- Recipes
- Performance
- Restraint and removal
- Debugging
- Never ship
- Motion exit gate
Should it animate
Decide before writing code. A decision to not animate is a valid result.
Never animate keyboard-initiated actions.
Name the purpose in one word before continuing:
- Feedback: the interface heard the user.
- Spatial consistency: where something came from or went.
- State indication: a state change made legible.
- Preventing a jarring change: content would otherwise teleport.
- Explanation: shows how something works (marketing and onboarding).
- Delight: only at the rare or first-time tier.
If no purpose can be named, do not build it. Data the user is reading or acting on should not move for style.
Pick the tool
Use the cheapest tool that works. Extend the project's existing motion tokens and library instead of adding a parallel system.
If the task needs a component rather than an animation (dialog, popover, menu, select, toast, drawer, command menu), use the project's accessible primitive or a proven headless library instead of hand-rolling focus and dismissal.
Pick the properties
- Animate
transformandopacityby default.clip-pathandfilterare acceptable with testing. Animateheightonly for accordions, where no transform equivalent exists. - Never animate from
scale(0). Start fromscale(0.9)toscale(0.97)combined withopacity: 0. - Use percentage translates (
translateY(100%)) for elements of unknown size. - Swap expensive properties for cheaper equivalents:
- Never use
transition: all. List the exact properties.
Easing, duration, and springs
Easing
Never use ease-in for UI motion. It delays the first frames, which is the moment the user watches most closely.
Built-in CSS curves are weak. Default tokens when the project has none:
Do not invent curves. Take additional curves from a curated source such as easing.dev or easings.co.
Duration
Keep product UI motion under 300ms unless the reference proves otherwise. Make exits faster than entrances.
Springs
Use springs for drag with momentum, gestures the user can reverse, elements that should feel alive, and decorative pointer tracking.
Keep bounce between 0 and 0.3. Add overshoot only when the gesture itself carried momentum.
Interruption, origin, and exit
- Use CSS transitions, not keyframes, for anything a user can trigger twice in a second. Transitions retarget from the current value; keyframes restart.
- Use springs for gestures. They carry velocity through interruption.
- Never lock out input during a transition. Start new motion from the current on-screen value.
- Set
transform-originat the trigger for popovers, dropdowns, menus, and tooltips. Modals stay centered. - Exit along the same path as the entrance.
- Use asymmetric timing where the user is deciding: slow on a deliberate press (hold to confirm, 2s linear), fast on release (200ms ease-out).
- Stagger group entrances by 30 to 80ms per item. Never block interaction while a stagger plays.
- After the first tooltip in a group opens, open neighbors instantly with no delay or animation.
Gestures
- Give feedback on pointer-down, and update 1:1 with the pointer during the drag. Respect the grab offset.
- Use
setPointerCaptureonce a drag starts. Ignore extra touch points mid-drag. - Dismiss on velocity as well as distance, so a quick flick works.
- Apply increasing resistance past boundaries instead of a hard stop.
- Write drag values directly to the element's
transform. Do not route them through a CSS variable on a parent or through React state. - Use native scroll snapping (
scroll-snap-type) for carousels before building a custom gesture.
Reduced motion and pointer gating
Ship these with the animation, not as follow-ups.
- Reduced motion means fewer and gentler animations, not zero. Keep opacity and color changes that aid comprehension. Remove slides, springs, parallax, and overshoot.
- Respect
prefers-reduced-transparencyandprefers-contrast: moreon translucent surfaces. - Avoid full-viewport moving backgrounds and slow looping oscillations.
- Content must stay visible if animation setup or JavaScript fails.
Recipes
Adapt these starting points to the project's tokens.
- When a crossfade shows two overlapping states, add
filter: blur(2px)during the transition. Keep animated blur under 20px. - For tab indicators with color changes, clip a duplicated active-state layer with
clip-pathinstead of timing separate color transitions. - For hold-to-confirm, fill a
clip-pathoverlay with linear timing on press and snap back on release.
Performance
The frame budget is 16.7ms at 60Hz and about 8ms at 120Hz. Design against the smaller number.
- JavaScript
requestAnimationFrameanimation runs on the main thread and drops frames during navigation, hydration, or data loading. Use CSS or WAAPI for motion that plays while the page is busy. - In Motion (Framer Motion), the
x,y, andscaleshorthands are not hardware-accelerated. Use a fulltransformstring when the animation must survive a busy main thread. - Never call
setStateevery frame. Write toref.current.styleor a motion value. - Changing an inherited CSS variable recalculates styles for every descendant. Suspect it when an animation degrades as content grows.
- Add
will-change: transformonly to the animating element and only after observing a one-pixel shift or measured dropped frames. - Virtualize long lists instead of animating thousands of nodes.
- Confirm with a Performance panel recording, not by feel, and on a mid-range device when possible.
Restraint and removal
Every animation must defend its place. Remove or reduce:
- Motion on keyboard actions and 100+ per-day surfaces.
- Fade-in-on-scroll applied to every section. On marketing pages, keep one hero entrance and reveals that explain something, fired once.
- Hover scale or lift on cards that are not the primary action.
- Infinite loops (pulsing badges, glowing borders, gradient orbs) on persistent elements.
- Charts that redraw from zero or numbers that count up on every mount instead of on a real change.
- Spinners and skeleton shimmer for operations that resolve in under 300ms.
Before deleting motion, also delete its hidden start state (opacity: 0 initial values, reveal classes) and any code waiting on it (transitionend, onAnimationEnd, timeouts, exit callbacks), and move focus logic that ran after the animation.
Debugging
- Play motion at 2 to 5 times its duration or in the DevTools Animations panel to check easing, origin, and property sync.
- Step frame by frame when a crossfade or coordinated property looks wrong.
- Test touch gestures on real hardware. Device emulation does not reproduce gesture feel.
Never ship
Motion exit gate
Confirm:
- Every animation has a frequency tier and a named purpose, or was removed.
- Observed reference motion was matched before defaults were applied.
- Properties, easing, and durations follow this playbook or the project's existing tokens.
- Rapid triggers retarget smoothly, and gestures can be interrupted and reversed.
- Hover motion is pointer-gated, and reduced-motion and reduced-transparency paths exist.
- No new frame drops appear in a recording during navigation or loading.
- Content remains visible and usable with animation disabled or JavaScript failing.
Adapted from Emil Kowalski's design-engineering skills (github.com/emilkowalski/skills, MIT license) and Apple's fluid-interface guidance.