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