--- name: auto-animate description: | Zero-config animations for React, Vue, Solid, Svelte, Preact with @formkit/auto-animate (3.28kb). Prevents 15 documented errors including React 19 StrictMode bugs, SSR imports, conditional parents, viewport issues, drag & drop conflicts, and CSS transform bugs. Use when: animating lists/accordions/toasts, troubleshooting SSR animation errors, React 19 StrictMode issues, or need accessible drop-in transitions with auto prefers-reduced-motion. user-invocable: true --- # AutoAnimate - Error Prevention Guide **Package**: @formkit/auto-animate@0.9.0 (current) **Frameworks**: React, Vue, Solid, Svelte, Preact **Last Updated**: 2026-01-21 --- ## SSR-Safe Pattern (Critical for Cloudflare Workers/Next.js) ```tsx // Use client-only import to prevent SSR errors import { useState, useEffect } from "react"; export function useAutoAnimateSafe() { const [parent, setParent] = useState(null); useEffect(() => { if (typeof window !== "undefined" && parent) { import("@formkit/auto-animate").then(({ default: autoAnimate }) => { autoAnimate(parent); }); } }, [parent]); return [parent, setParent] as const; } ``` **Why this matters**: Prevents Issue #1 (SSR/Next.js import errors). AutoAnimate uses DOM APIs not available on server. --- ## Known Issues Prevention (15 Documented Errors) This skill prevents **15** documented issues: ### Issue #1: SSR/Next.js Import Errors **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`) ### Issue #2: Conditional Parent Rendering **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**: **React Pattern**: ```tsx // ❌ Wrong {showList && } // ✅ Correct ``` **Vue.js Pattern**: ```vue ``` **Source**: React [Issue #8](https://github.com/formkit/auto-animate/issues/8), Vue [Issue #193](https://github.com/formkit/auto-animate/issues/193) ### Issue #3: Missing Unique Keys **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}`) ### Issue #4: Flexbox Width and Shaking Issues **Error**: Elements snap to width instead of animating smoothly, or container shakes on remove **Source**: Official docs, [Issue #212](https://github.com/formkit/auto-animate/issues/212) **Why It Happens**: `flex-grow: 1` waits for surrounding content, causing timing issues **Prevention**: Use explicit width instead of flex-grow for animated elements ```tsx // ❌ Wrong - causes shaking // ✅ Correct - fixed sizes ``` **Maintainer Note**: justin-schroeder confirmed fixed sizes are required for flex containers ### Issue #5: Table Row Display Issues **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 `` instead of individual rows, or use div-based layouts ### Issue #6: Jest Testing Errors **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 ### Issue #7: esbuild Compatibility **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 ### Issue #8: CSS Position Side Effects **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 ### Issue #9: Vue/Nuxt Registration Errors **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/) **Nuxt 3 Note**: Requires v0.8.2+ (April 2024). Earlier versions have ESM import issues fixed by Daniel Roe. See [Issue #199](https://github.com/formkit/auto-animate/issues/199) ### Issue #10: Angular ESM Issues **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 ### Issue #11: React 19 StrictMode Double-Call Bug **Error**: Child animations don't work in React 19 StrictMode **Source**: https://github.com/formkit/auto-animate/issues/232 **Why It Happens**: StrictMode calls useEffect twice, triggering autoAnimate initialization twice **Prevention**: Use ref to track initialization ```tsx // ❌ Wrong - breaks in StrictMode const [parent] = useAutoAnimate(); // ✅ Correct - prevents double initialization const [parent] = useAutoAnimate(); const initialized = useRef(false); useEffect(() => { if (initialized.current) return; initialized.current = true; }, []); ``` **Note**: React 19 enables StrictMode by default in development. This affects all React 19+ projects. ### Issue #12: Broken Animation Outside Viewport **Error**: Animations broken when list is outside viewport **Source**: https://github.com/formkit/auto-animate/issues/222 **Why It Happens**: Chrome may not run Animation API for off-screen elements **Prevention**: Ensure parent is visible before applying autoAnimate ```tsx const isInViewport = (element) => { const rect = element.getBoundingClientRect(); return rect.top >= 0 && rect.bottom <= window.innerHeight; }; useEffect(() => { if (parent.current && isInViewport(parent.current)) { autoAnimate(parent.current); } }, [parent]); ``` ### Issue #13: Deleted Elements Overlay Existing Content **Error**: Removed items overlay other items during fade out **Source**: https://github.com/formkit/auto-animate/issues/231 **Why It Happens**: Exit animation maintains z-index, covering active content **Prevention**: Add explicit z-index handling ```tsx // CSS workaround ``` ### Issue #14: Cannot Disable During Drag & Drop **Error**: Calling enable(false) doesn't prevent animations during drag **Source**: https://github.com/formkit/auto-animate/issues/215 **Why It Happens**: Disable doesn't work reliably mid-drag **Prevention**: Conditionally remove ref during drag ```tsx const [isDragging, setIsDragging] = useState(false); const [parent] = useAutoAnimate(); return ( ); ``` ### Issue #15: CSS Transform Parent Position Bug **Error**: Items animate from wrong position after parent transform **Source**: https://github.com/formkit/auto-animate/issues/227 **Why It Happens**: Items remember original position before transform **Prevention**: Delay autoAnimate until transform completes ```tsx useEffect(() => { if (showList && parent.current) { setTimeout(() => { autoAnimate(parent.current); }, 300); // Match CSS transition duration } }, [showList]); ``` --- ## Critical Rules (Error Prevention) ### Always Do ✅ **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 ### Never Do ❌ **Conditional parent** - `{show &&