plugins/frontend-toolkit/skills/animation-quality/SKILL.md
Audit and improve animations for 60fps, prefers-reduced-motion compliance, motion-feel (duration/easing), and accessibility. Use when jank appears in scroll/interaction, INP regresses, an animation auto-plays/loops or flashes, or before shipping. Not for diagnosing broad Core Web Vitals regressions (use rendering-performance) or full WCAG conformance auditing (use accessibility-audit).
npx skillsauth add jaykim88/claude-ai-engineering animation-qualityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
All animations stay on the compositor thread (60fps), respect user motion preferences, and use the right tool (CSS vs JS) for the job.
Universal — GPU-compositor rules (transform/opacity only), prefers-reduced-motion compliance, CSS-vs-JS choice, and 60fps target are browser-level concerns identical across frameworks.
Audit animated properties — restrict to compositor-friendly props
transform (translate/scale/rotate/skew), opacity, filtertop, left, width, height, margin, padding (trigger layout/paint)height: auto) are the classic offender — reserve the space, or animate transform / grid-template-rows: 0fr→1fr instead of heightgrep -rE 'transition.*?(width|height|top|left|margin|padding)' src/Respect prefers-reduced-motion globally
transform and layout animations while preserving opacity and color transitions — not all motion is killed. This is the intended behavior (preserves accessibility-safe feedback).Audit will-change usage
will-change should be applied just before animation, removed afterwill-change on many elements degrades performancewill-changeChoose the right tool — and tune the feel
linear for UI motion (reserve it for continuous/looping)Use the animation library's primitives correctly
AnimatePresence / layout / layoutId)Scroll-driven animations
IntersectionObserver or Motion's useScrollscroll event listeners (run on main thread)JS animations use requestAnimationFrame
setTimeout for animation loopsrAF on cleanupVerify (validation loop)
| Tier | Examples | Action SLA |
|---|---|---|
| Critical | Content flashes >3×/second (seizure risk, WCAG 2.3.1); prefers-reduced-motion ignored entirely; auto-playing motion >5s with no pause control (WCAG 2.2.2) | Block release; fix immediately |
| Major | Animating layout props (top/width/height) causing jank or CLS; dropped frames in the Performance trace; permanent will-change on many elements | Fix this sprint |
| Minor | Sluggish duration / wrong easing; missing exit (AnimatePresence) animations; scroll listener instead of IntersectionObserver | Schedule within 2 sprints |
transform/opacity/filterprefers-reduced-motion honored globallywill-change permanent declarationsAnimatePresence covers all conditional renders with exit animations<MotionConfig reducedMotion="user"> (or framework equivalent) wired at app rootdocs/perf-trace-YYYY-MM-DD.jsonfix(anim): switch <component> to transform/opacity for fixes; feat(anim): add <interaction> for new<MotionConfig reducedMotion="user">, useReducedMotion() hook, <AnimatePresence>, layout + layoutIdmotion-reduce:transition-none<Transition> / <TransitionGroup> built-in; @vueuse/motion for spring physics; prefers-reduced-motion via Tailwind variant or CSStransition: directive (fade, fly, scale, crossfade) + motion package; prefers-reduced-motion store available via @svelte-put/preferences@angular/animations module with trigger(), state(), animate(); BreakpointObserver for reduced-motion media queryprefers-reduced-motion is a CSS media query that any framework can detect; Chrome DevTools Performance panel measures dropped frames framework-agnosticallyrendering-performance — animation jank often manifests as INP regressionaccessibility-audit — reduced-motion respect is a WCAG requirement<MotionConfig reducedMotion="user"> for global opt-out — single source of truth. Constrain animated props to transform/opacity so animations stay on the GPU (and don't shift layout → CLS). Prefer layout over manual position animation for free FLIP-style transitions. Motion-specific WCAG lives in this skill, not just reduced-motion: nothing flashes >3×/s (2.3.1), and auto-playing motion >5s must be pausable (2.2.2). Tune the feel — fast durations (100–300ms) with ease-out entrances / ease-in exits.development
Audit and optimize third-party scripts — analytics, tag managers, chat widgets, embeds — with the right loading strategy, performance budget, facades, and CSP/consent controls. Use when adding a script, when TBT/INP regress, when a GDPR/CCPA consent requirement arises, or before shipping. Not for first-party bundle size (use bundle-optimization) or broad Core Web Vitals diagnosis (use rendering-performance).
development
Apply the Testing Trophy (mostly integration tests with RTL + MSW, sparing E2E with Playwright) and set coverage thresholds. Use before new feature work, after bug fixes, when CI coverage falls below target, or when tests are flaky or break on every refactor. Not for wiring coverage gates + Playwright into the GitHub Actions matrix (use cicd-pipeline) or auditing WCAG a11y compliance (use accessibility-audit).
development
Inventory and prioritize technical debt — TODO/FIXME/HACK, any usage, deprecated APIs, untested logic — with impact × effort matrix. Use at quarter start, before a refactoring sprint, when a new teammate joins, or when feature velocity slows. Not for actually paying down debt (use code-refactoring) or recording a migration approach (use decision-records) — this only inventories and prioritizes.
development
Decision framework for choosing the right state location — URL, server cache, local component, or shared/global store. Use when state-sync bugs appear, prop drilling gets deep (3+ levels), filters/tabs lose state on reload, or quarterly review. Not for form state specifically (use form-ux) or when the state is actually server data (use api-caching-optimization).