```
Compiles to: `animate={{ scale: [1, 1.2, 1] }}`
## Transition Configuration
All transition classes have NO gesture prefix:
| Class | Compiled to | Notes |
|---|---|---|
| `animate-duration-{ms}` | `duration: ms/1000` | Duration in ms |
| `animate-delay-{ms}` | `delay: ms/1000` | Start delay |
| `animate-spring` | `type: "spring"` | Spring physics |
| `animate-stiffness-{n}` | `stiffness: n` | Spring tension |
| `animate-damping-{n}` | `damping: n` | Spring resistance |
| `animate-mass-{n}` | `mass: n/10` | Object weight |
| `animate-bounce-{n}` | `bounce: n/100` | Bounciness |
| `animate-ease-in` | `ease: "easeIn"` | Slow start |
| `animate-ease-out` | `ease: "easeOut"` | Slow end |
| `animate-ease-in-out` | `ease: "easeInOut"` | Slow both |
| `animate-ease-linear` | `ease: "linear"` | Constant speed |
| `animate-ease-circ-in` | `ease: "circIn"` | Circular ease in |
| `animate-ease-circ-out` | `ease: "circOut"` | Circular ease out |
| `animate-ease-circ-in-out` | `ease: "circInOut"` | Circular ease in-out |
| `animate-ease-back-in` | `ease: "backIn"` | Enters with overshoot |
| `animate-ease-back-out` | `ease: "backOut"` | Exits with anticipation |
| `animate-ease-back-in-out` | `ease: "backInOut"` | Both |
| `animate-ease-anticipate` | `ease: "anticipate"` | Pull back then forward |
| `animate-ease-[n,n,n,n]` | `ease: [n,n,n,n]` | Custom cubic-bezier |
| `animate-ease-steps-{n}` | `ease: "steps(n)"` | Stepped animation |
| `animate-repeat-{n}` | `repeat: n` | Fixed repeat count |
| `animate-repeat-infinite` | `repeat: Infinity` | Loop forever |
| `animate-repeat-reverse` | `repeatType: "reverse"` | Alternate direction |
| `animate-repeat-mirror` | `repeatType: "mirror"` | Mirror direction |
| `animate-repeat-delay-{ms}` | `repeatDelay: ms/1000` | Pause between cycles |
| `animate-stagger-{ms}` | `staggerChildren: ms/1000` | Stagger children (on parent) |
| `animate-stagger-reverse` | `staggerDirection: -1` | Reverse stagger |
| `animate-delay-children-{ms}` | `delayChildren: ms/1000` | Delay all children |
| `animate-when-before` | `when: "beforeChildren"` | Parent first |
| `animate-when-after` | `when: "afterChildren"` | Children first |
| `animate-rest-speed-{n}` | `restSpeed: n` | Spring rest velocity |
| `animate-rest-delta-{n}` | `restDelta: n` | Spring rest distance |
| `animate-times-[...]` | `times: [...]` | Keyframe timing |
## Viewport Configuration (for inview gesture)
| Class | Effect |
|---|---|
| `animate-once` | `viewport.once: true` -- only animate once |
| `animate-amount-all` | `viewport.amount: "all"` -- fully visible |
| `animate-amount-{n}` | `viewport.amount: n/100` -- percentage |
| `animate-margin-{n}` | `viewport.margin: "{n}px"` -- early trigger |
## Drag Configuration
| Class | Effect |
|---|---|
| `animate-drag-x` | `drag="x"` |
| `animate-drag-y` | `drag="y"` |
| `animate-drag-both` | `drag` (both axes) |
| `animate-drag-elastic-{n}` | `dragElastic={n/100}` |
| `animate-drag-snap` | `dragSnapToOrigin` |
| `animate-drag-no-momentum` | `dragMomentum={false}` |
| `animate-drag-lock` | `dragDirectionLock` |
| `animate-drag-constraint-t-{n}` | `dragConstraints.top: n` |
| `animate-drag-constraint-b-{n}` | `dragConstraints.bottom: n` |
| `animate-drag-constraint-l-{n}` | `dragConstraints.left: n` |
| `animate-drag-constraint-r-{n}` | `dragConstraints.right: n` |
## Layout Configuration
| Class | Effect |
|---|---|
| `animate-layout` | `layout` |
| `animate-layout-position` | `layout="position"` |
| `animate-layout-size` | `layout="size"` |
| `animate-layout-preserve` | `layout="preserve-aspect"` |
| `animate-layout-id-{name}` | `layoutId="{name}"` |
| `animate-layout-scroll` | `layoutScroll` |
| `animate-layout-root` | `layoutRoot` |
## Dynamic ClassNames (Runtime)
For dynamic/conditional classNames, use `mw.*` components:
```tsx
import { mw } from "motionwind-react";
Dynamic
```
`mw.*` supports all HTML tags via Proxy. When className has no `animate-*` classes, it renders a plain HTML element. Results are cached by className string.
## API Reference
### parseMotionClasses(className)
```tsx
import { parseMotionClasses } from "motionwind-react";
const result = parseMotionClasses("bg-blue-500 p-4 animate-hover:scale-110 animate-duration-300");
// Returns: { tailwindClasses, gestures, transition, viewport, dragConfig, layoutConfig, hasMotion }
```
### clearParserCache()
```tsx
import { clearParserCache } from "motionwind-react";
clearParserCache();
```
## Common Patterns
### Interactive Button (hover + tap)
```html
Click Me
```
### 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
Springy
```
### Draggable Element
```html
Drag me
```
### SVG Path Drawing
```html
```
### Staggered Children
```html
```
### Layout Animation
```html
Automatically animates when layout changes
```
### Shared Layout (layoutId)
```html
{activeTab === tab && (
)}
```
### 3D Card Hover (needs parent with perspective)
```html
```
### Color Animation
```html
Hover for color
```
## 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.