diff --git a/README.md b/README.md
index 7a23380..9178063 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,7 @@ Timing animations transition from one value to another over a fixed duration wit
| ---------- | ------------ | ------------- | ------------------------------------------------------------------------ |
| `duration` | `number` | `300` | Duration in milliseconds |
| `easing` | `EasingType` | `'easeInOut'` | Easing curve (preset name or `[x1, y1, x2, y2]` cubic bezier) |
+| `delay` | `number` | `0` | Delay in milliseconds before the animation starts |
| `loop` | `string` | — | `'repeat'` restarts from the beginning, `'reverse'` alternates direction |
Available easing curves:
@@ -146,6 +147,7 @@ Spring animations use a physics-based model for natural-feeling motion. Great fo
| `damping` | `number` | `15` | Friction — higher values reduce oscillation |
| `stiffness` | `number` | `120` | Spring constant — higher values mean faster animation |
| `mass` | `number` | `1` | Mass of the object — higher values mean slower, more momentum |
+| `delay` | `number` | `0` | Delay in milliseconds before the animation starts |
Spring presets for common feels:
@@ -276,6 +278,26 @@ Use `initialAnimate` to set starting values. On mount, the view starts at `initi
Without `initialAnimate`, the view renders at the `animate` values immediately with no animation on mount.
+### Delay
+
+Use `delay` to postpone the start of an animation. This is useful for staggering enter animations across multiple elements.
+
+```tsx
+// Staggered fade-in list
+{items.map((item, i) => (
+
+ {item.label}
+
+))}
+```
+
+`delay` works with both timing and spring transitions.
+
### Interruption
Animations are interruptible by default. If you change `animate` values while an animation is running, it smoothly redirects to the new target from wherever it currently is — no jumping or restarting.
@@ -386,6 +408,7 @@ Properties not specified in `animate` default to their identity values.
type: 'timing';
duration?: number; // default: 300 (ms)
easing?: EasingType; // default: 'easeInOut' — preset name or [x1, y1, x2, y2]
+ delay?: number; // default: 0 (ms)
loop?: 'repeat' | 'reverse'; // default: none
}
```
@@ -398,6 +421,7 @@ Properties not specified in `animate` default to their identity values.
damping?: number; // default: 15
stiffness?: number; // default: 120
mass?: number; // default: 1
+ delay?: number; // default: 0 (ms)
}
```
diff --git a/skills/react-native-ease-refactor/SKILL.md b/skills/react-native-ease-refactor/SKILL.md
index 22f207e..3c65981 100644
--- a/skills/react-native-ease-refactor/SKILL.md
+++ b/skills/react-native-ease-refactor/SKILL.md
@@ -52,7 +52,9 @@ Apply these checks in order. The first match determines the result:
2. **Uses scroll handler?** (`useAnimatedScrollHandler`, `onScroll` with `Animated.event`) → NOT migratable — "Scroll-driven animation"
3. **Uses shared element transitions?** (`sharedTransitionTag`) → NOT migratable — "Shared element transition"
4. **Uses `runOnUI` or worklet directives?** → NOT migratable — "Requires worklet runtime"
-5. **Uses `withSequence` or `withDelay`?** → NOT migratable — "Animation sequencing not supported"
+5. **Uses `withSequence`?** → NOT migratable — "Animation sequencing not supported"
+5b. **Uses `withDelay` wrapping a single animation (`withTiming`/`withSpring`)?** → MIGRATABLE — map to `delay` on the transition
+5c. **Uses `withDelay` wrapping `withSequence` or nested `withDelay`?** → NOT migratable — "Complex delay/sequencing not supported"
6. **Uses complex `interpolate()`?** (more than 2 input/output values) → NOT migratable — "Complex interpolation"
7. **Uses `layout={...}` prop?** → NOT migratable — "Layout animation"
8. **Animates unsupported properties?** (anything besides: opacity, translateX, translateY, scale, scaleX, scaleY, rotate, rotateX, rotateY, borderRadius, backgroundColor) → NOT migratable — "Animates unsupported property: ``"
@@ -83,6 +85,8 @@ Use this table to convert Reanimated/Animated patterns to EaseView:
| `Easing.bezier(x1, y1, x2, y2)` | `easing: [x1, y1, x2, y2]` |
| `Animated.Value` + `Animated.timing` | Same `animate` + `transition` pattern — convert to state-driven |
| `Animated.Value` + `Animated.spring` | `animate` + `transition={{ type: 'spring' }}` — convert to state-driven |
+| `withDelay(ms, withTiming(...))` or `withDelay(ms, withSpring(...))` | `transition={{ ..., delay: ms }}` — add `delay` to the transition config |
+| `entering={FadeIn.delay(ms)}` / any entering preset with `.delay()` | `initialAnimate` + `animate` + `transition={{ ..., delay: ms }}` |
### Default Value Mapping
@@ -360,6 +364,7 @@ transition={{
type: 'timing',
duration: 300, // ms, default 300
easing: 'easeInOut', // 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | [x1,y1,x2,y2]
+ delay: 0, // ms, default 0
loop: 'repeat', // 'repeat' | 'reverse' — requires initialAnimate
}}
```
@@ -372,6 +377,7 @@ transition={{
damping: 15, // default 15
stiffness: 120, // default 120
mass: 1, // default 1
+ delay: 0, // ms, default 0
}}
```
@@ -394,6 +400,6 @@ transition={{ type: 'none' }}
- **Loop requires timing** (not spring) and `initialAnimate` must define the start value
- **No per-property transitions** — one transition config applies to all animated properties
-- **No animation sequencing** — no equivalent to `withSequence`/`withDelay`
+- **No animation sequencing** — no equivalent to `withSequence`. Simple `withDelay` IS supported via the `delay` transition prop
- **No gesture/scroll-driven animations** — EaseView is state-driven only
- **Style/animate conflict** — if a property appears in both `style` and `animate`, the animated value wins