# motionwind — Complete Documentation for LLMs ## What is motionwind? motionwind is a Babel plugin that transforms Tailwind-like animation classes into Motion (formerly Framer Motion) component props at build time. Write `animate-hover:scale-110` and it becomes `whileHover={{ scale: 1.1 }}`. Zero imports, zero boilerplate, zero runtime overhead. ## Installation ### Prerequisites - React 18+ - Motion 11+ (the `motion` package) - Node.js 18+ ### Quick Start ```bash npx create-motionwind ``` Or manually: ```bash npm install motionwind-react motion ``` ### Next.js Setup ```js // next.config.js import withMotionwind from "motionwind-react/next"; export default withMotionwind({}); ``` ### Vite Setup (plugin must come BEFORE react) ```ts import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import { motionwind } from "motionwind-react/vite"; export default defineConfig({ plugins: [motionwind(), react()] }); ``` ### Babel Setup ```json { "plugins": ["motionwind-react/babel"] } ``` ## How It Works The Babel plugin: 1. Scans JSX for static `className` strings with `animate-*` tokens 2. Parses them into Motion props 3. Rewrites `
` to `` with parsed props 4. Auto-injects `"use client"` and `import { motion } from "motion/react"` 5. Tailwind classes pass through unchanged ### Key Constraints - **Static classNames only** — template literals/variables are NOT transformed. Use `mw.*` for dynamic. - **Lowercase HTML elements only** — `
`, ` ``` ### Scroll Reveal (fade + slide up, once) ```html
Scroll to reveal
``` ### Mount Animation (fade up on load) ```html
Fades in on mount
``` ### Exit Animation (requires AnimatePresence wrapper) ```tsx import { AnimatePresence } from "motion/react"; {show && (
Conditional content
)}
``` ### Infinite Spin ```html
Spinning
``` ### Pulse/Breathing Effect ```html
Pulsing
``` ### Spring Button ```html ``` ### Draggable Element ```html
Drag me
``` ### SVG Path Drawing ```html ``` ### Staggered Children ```html
First
Second
Third
``` ### Layout Animation ```html
Automatically animates when layout changes
``` ### Shared Layout (layoutId) ```html {activeTab === tab && (
)} ``` ### 3D Card Hover (needs parent with perspective) ```html
3D hover card
``` ### Color Animation ```html ``` ## Troubleshooting 1. **Classes not transforming?** -- Must be static string literals on lowercase HTML elements. Use `mw.*` for dynamic. 2. **Animations not working in production?** -- Check that `withMotionwind` (Next.js) or `motionwind()` (Vite) is in your config. 3. **Exit animations not playing?** -- Wrap in `` from `motion/react`. 4. **Plugin order matters (Vite)** -- `motionwind()` MUST come before `react()` in plugins array. 5. **Server Component errors?** -- Extract animated elements into separate component files. The plugin auto-adds `"use client"`. ## Gesture Priority (highest to lowest) 1. Tap (overrides all while pressed) 2. Focus 3. Hover 4. InView / Enter (lowest) --- # motionwind-react-native — React Native Support ## What is motionwind-react-native? motionwind-react-native brings the same Tailwind-like animation syntax to React Native, powered by react-native-reanimated. Write `animate-tap:scale-95` and it runs a 60fps native animation via Reanimated shared values. Runtime parsing with LRU cache, no Babel step needed. ## Installation ### Prerequisites - React 18+ or 19+ - React Native 0.72+ - react-native-reanimated 3.x or 4.x ### Expo Setup ```bash npx expo install react-native-reanimated react-native-gesture-handler npm install motionwind-react-native ``` ### Bare React Native ```bash npm install motionwind-react-native react-native-reanimated react-native-gesture-handler ``` Babel config (Reanimated plugin must be last): ```js module.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: ["react-native-reanimated/plugin"], }; }; ``` ## Usage ```tsx import { mw } from "motionwind-react-native"; // Fade-in on mount Fades in // Tap interaction Press me // Spring animation Bounces in ``` ## Available Components `mw.View`, `mw.Text`, `mw.Image`, `mw.Pressable`, `mw.ScrollView`, `mw.FlatList`, `mw.TextInput`, `mw.TouchableOpacity`, `mw.SafeAreaView` When no `animate-*` classes are present, renders plain (non-animated) components. ## Hooks ### useMotionwind(className) ```tsx import { useMotionwind } from "motionwind-react-native"; const { animatedStyle, handlers, parsed, animateTo, resetToBase } = useMotionwind(className); ``` ### useInView() ```tsx import { useInView } from "motionwind-react-native"; const { isInView, onLayout, viewRef } = useInView(); ``` ## Native-Specific Differences | Feature | Web (motionwind-react) | Native (motionwind-react-native) | |---|---|---| | Animation engine | Motion (Framer Motion) | react-native-reanimated | | Transform | Build-time Babel | Runtime parsing | | Styling | Tailwind CSS | NativeWind (optional) | | CSS filters (blur, brightness) | Supported | Silently dropped | | CSS units (vh, vw, rem) | Supported | Plain numbers (dp) | | Rotate values | Number (degrees) | String ("45deg") auto-formatted | | Duration unit | Seconds (0.3) | Milliseconds (300) | ## Syntax Same `animate-*` syntax as web. All gesture prefixes, animatable properties, transition config, viewport config, and drag config classes work identically. See the web syntax reference above. Properties silently dropped on native: filter/blur/brightness/contrast/saturate, backdrop-blur, clip, path-length/offset/spacing, box-shadow.