**Status**: Production Ready ✅
/plugin marketplace add secondsky/claude-skills/plugin install auto-animate@claude-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/example-template.txtreferences/auto-animate-vs-motion.mdreferences/css-conflicts.mdreferences/example-reference.mdreferences/ssr-patterns.mdscripts/example-script.shscripts/init-auto-animate.shtemplates/accordion.tsxtemplates/filter-sort-list.tsxtemplates/form-validation.tsxtemplates/react-basic.tsxtemplates/react-typescript.tsxtemplates/toast-notifications.tsxtemplates/vite-ssr-safe.tsxStatus: Production Ready ✅ Last Updated: 2025-11-07 Dependencies: None (works with any React setup) Latest Versions: @formkit/auto-animate@0.9.0
bun add @formkit/auto-animate
Why this matters:
import { useAutoAnimate } from "@formkit/auto-animate/react";
export function MyList() {
const [parent] = useAutoAnimate(); // 1. Get ref
return (
<ul ref={parent}> {/* 2. Attach to parent */}
{items.map(item => (
<li key={item.id}>{item.text}</li> {/* 3. That's it! */}
))}
</ul>
);
}
CRITICAL:
prefers-reduced-motion automaticallyFor Cloudflare Workers or Next.js:
// Use client-only import to prevent SSR errors
import { useState, useEffect } from "react";
export function useAutoAnimateSafe<T extends HTMLElement>() {
const [parent, setParent] = useState<T | null>(null);
useEffect(() => {
if (typeof window !== "undefined" && parent) {
import("@formkit/auto-animate").then(({ default: autoAnimate }) => {
autoAnimate(parent);
});
}
}, [parent]);
return [parent, setParent] as const;
}
This skill prevents 10+ documented issues:
Error: "Can't import the named export 'useEffect' from non EcmaScript module"
Source: https://github.com/formkit/auto-animate/issues/55
Why It Happens: AutoAnimate uses DOM APIs not available on server
Prevention: Use dynamic imports (see templates/vite-ssr-safe.tsx)
Error: Animations don't work when parent is conditional Source: https://github.com/formkit/auto-animate/issues/8 Why It Happens: Ref can't attach to non-existent element Prevention:
// ❌ Wrong
{showList && <ul ref={parent}>...</ul>}
// ✅ Correct
<ul ref={parent}>{showList && items.map(...)}</ul>
Error: Items don't animate correctly or flash
Source: Official docs
Why It Happens: React can't track which items changed
Prevention: Always use unique, stable keys (key={item.id})
Error: Elements snap to width instead of animating smoothly
Source: Official docs
Why It Happens: flex-grow: 1 waits for surrounding content
Prevention: Use explicit width instead of flex-grow for animated elements
Error: Table structure breaks when removing rows
Source: https://github.com/formkit/auto-animate/issues/7
Why It Happens: Display: table-row conflicts with animations
Prevention: Apply to <tbody> instead of individual rows, or use div-based layouts
Error: "Cannot find module '@formkit/auto-animate/react'"
Source: https://github.com/formkit/auto-animate/issues/29
Why It Happens: Jest doesn't resolve ESM exports correctly
Prevention: Configure moduleNameMapper in jest.config.js
Error: "Path '.' not exported by package" Source: https://github.com/formkit/auto-animate/issues/36 Why It Happens: ESM/CommonJS condition mismatch Prevention: Configure esbuild to handle ESM modules properly
Error: Layout breaks after adding AutoAnimate
Source: Official docs
Why It Happens: Parent automatically gets position: relative
Prevention: Account for position change in CSS or set explicitly
Error: "Failed to resolve directive: auto-animate" Source: https://github.com/formkit/auto-animate/issues/43 Why It Happens: Plugin not registered correctly Prevention: Proper plugin setup in Vue/Nuxt config (see references/)
Error: Build fails with "ESM-only package" Source: https://github.com/formkit/auto-animate/issues/72 Why It Happens: CommonJS build environment Prevention: Configure ng-packagr for Angular Package Format
Rule of Thumb: Use AutoAnimate for 90% of cases, Motion for hero/interactive animations.
✅ Use unique, stable keys - key={item.id} not key={index}
✅ Keep parent in DOM - Parent ref element always rendered
✅ Client-only for SSR - Dynamic import for server environments
✅ Respect accessibility - Keep disrespectUserMotionPreference: false
✅ Test with motion disabled - Verify UI works without animations
✅ Use explicit width - Avoid flex-grow on animated elements
✅ Apply to tbody for tables - Not individual rows
❌ Conditional parent - {show && <ul ref={parent}>}
❌ Index as key - key={index} breaks animations
❌ Ignore SSR - Will break in Cloudflare Workers/Next.js
❌ Force animations - disrespectUserMotionPreference: true breaks accessibility
❌ Animate tables directly - Use tbody or div-based layout
❌ Skip unique keys - Required for proper animation
❌ Complex animations - Use Motion instead
AutoAnimate is zero-config by default. Optional customization:
import { useAutoAnimate } from "@formkit/auto-animate/react";
const [parent] = useAutoAnimate({
duration: 250, // milliseconds (default: 250)
easing: "ease-in-out", // CSS easing (default: "ease-in-out")
// disrespectUserMotionPreference: false, // Keep false!
});
Recommendation: Use defaults unless you have specific design requirements.
Copy-paste ready examples:
react-basic.tsx - Simple list with add/remove/shufflereact-typescript.tsx - Typed setup with custom configfilter-sort-list.tsx - Animated filtering and sortingaccordion.tsx - Expandable sectionstoast-notifications.tsx - Fade in/out messagesform-validation.tsx - Error messages animationvite-ssr-safe.tsx - Cloudflare Workers/SSR patternauto-animate-vs-motion.md - Decision guide for which to usecss-conflicts.md - Flexbox, table, and position gotchasssr-patterns.md - Next.js, Nuxt, Workers workaroundsinit-auto-animate.sh - Automated setup scriptAutoAnimate works perfectly with Cloudflare Workers Static Assets:
✅ Client-side only - Runs in browser, not Worker runtime ✅ No Node.js deps - Pure browser code ✅ Edge-friendly - 3.28 KB gzipped ✅ SSR-safe - Use dynamic imports (see templates/)
Vite Config:
export default defineConfig({
plugins: [react(), cloudflare()],
ssr: {
external: ["@formkit/auto-animate"],
},
});
AutoAnimate respects prefers-reduced-motion automatically:
/* User's system preference */
@media (prefers-reduced-motion: reduce) {
/* AutoAnimate disables animations automatically */
}
Critical: Never set disrespectUserMotionPreference: true - this breaks accessibility.
{
"dependencies": {
"@formkit/auto-animate": "^0.9.0"
},
"devDependencies": {
"react": "^19.2.0",
"vite": "^6.0.0"
}
}
This skill is based on production testing:
Tested Scenarios:
Solution: Check these common issues:
Solution: Use dynamic import:
useEffect(() => {
if (typeof window !== "undefined") {
import("@formkit/auto-animate").then(({ default: autoAnimate }) => {
autoAnimate(parent);
});
}
}, [parent]);
Solution: Add unique keys: key={item.id} not key={index}
Solution: Use explicit width instead of flex-grow: 1
Solution: Apply ref to <tbody>, not individual <tr> elements
@formkit/auto-animate@0.9.0prefers-reduced-motionQuestions? Issues?
templates/ for working examplesreferences/auto-animate-vs-motion.md for library comparisonreferences/ssr-patterns.md for SSR workaroundsProduction Ready? ✅ Yes - 13.6k stars, actively maintained, zero dependencies.