Animations
Skill Shankulkarni/react-native-ai-plugin/plugins/rn-ai/skills/animations
Write better React Native code from day one - opinionated Claude Code rules, New Architecture ready.
npx -y skills add Shankulkarni/react-native-ai-plugin --skill animationsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when implementing animations or gestures -- GPU-only properties, Reanimated v3 worklets, useDerivedValue, GestureDetector press states, layout animations, React Compiler compatibility.
SKILL.md
4.2 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it
Animations + Gestures
Reanimated v3 + Gesture Handler v2. New Architecture only. No RN core Animated API.
CRITICAL -- Only GPU-Accelerated Properties
// ❌ Causes layout recalculation every frame
width, height, top, left, margin, padding
// ✅ GPU-accelerated -- animate freely
transform: [{ translateX }, { translateY }, { scale }, { rotate }]
opacity
Core Imports
import Animated, {
useSharedValue, useAnimatedStyle, useDerivedValue,
useAnimatedReaction, withSpring, withTiming, withSequence,
withDelay, withRepeat, runOnJS, interpolate,
interpolateColor, Extrapolation, cancelAnimation,
FadeIn, FadeOut, SlideInRight, ZoomIn,
} from 'react-native-reanimated'
import { Gesture, GestureDetector } from 'react-native-gesture-handler'
// Always Animated.View from reanimated -- never from react-native
Animated Press State
function AnimatedCard({ onPress, children }: { onPress?: () => void; children: ReactNode }) {
const scale = useSharedValue(1)
const opacity = useSharedValue(1)
const tap = Gesture.Tap()
.onBegin(() => {
scale.value = withSpring(0.96, { damping: 15, stiffness: 300 })
opacity.value = withTiming(0.85, { duration: 80 })
})
.onFinalize((_, success) => {
scale.value = withSpring(1, { damping: 15, stiffness: 300 })
opacity.value = withTiming(1, { duration: 120 })
if (success && onPress) runOnJS(onPress)()
})
const style = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
opacity: opacity.value,
}))
return (
<GestureDetector gesture={tap}>
<Animated.View style={style}>{children}</Animated.View>
</GestureDetector>
)
}
useDerivedValue vs useAnimatedReaction
// ✅ useDerivedValue -- compute a new value (runs on UI thread)
const rotation = useDerivedValue(() => `${progress.value * 360}deg`)
const clamped = useDerivedValue(() =>
interpolate(raw.value, [0, 1], [0.8, 1.2], Extrapolation.CLAMP)
)
// ✅ useAnimatedReaction -- side effects only (call JS, haptics)
useAnimatedReaction(
() => progress.value,
(current, prev) => {
if (current >= 1 && prev !== null && prev < 1) runOnJS(onComplete)()
},
)
Layout Animations
// Entering/exiting animations on mount/unmount
<Animated.View entering={FadeIn.duration(300)} exiting={FadeOut.duration(200)}>
<Text>Fades in</Text>
</Animated.View>
<Animated.View entering={SlideInRight.springify().damping(15)}>
<Card />
</Animated.View>
// List item animations
<FlashList
renderItem={({ item, index }) => (
<Animated.View entering={FadeIn.delay(index * 50)}>
<PostCard {...item} />
</Animated.View>
)}
/>
Pan Gesture (Swipe to Dismiss)
function SwipeToDismiss({ onDismiss, children }: { onDismiss: () => void; children: ReactNode }) {
const x = useSharedValue(0)
const THRESHOLD = 100
const pan = Gesture.Pan()
.onUpdate((e) => { x.value = e.translationX })
.onEnd((e) => {
if (Math.abs(e.translationX) > THRESHOLD) runOnJS(onDismiss)()
else x.value = withSpring(0)
})
const style = useAnimatedStyle(() => ({
transform: [{ translateX: x.value }],
opacity: interpolate(Math.abs(x.value), [0, THRESHOLD], [1, 0.5], Extrapolation.CLAMP),
}))
return (
<GestureDetector gesture={pan}>
<Animated.View style={style}>{children}</Animated.View>
</GestureDetector>
)
}
Spring Presets
const SPRING = {
snappy: { damping: 20, stiffness: 400 },
bouncy: { damping: 10, stiffness: 200, mass: 0.8 },
gentle: { damping: 30, stiffness: 150 },
}
// Usage
scale.value = withSpring(1, SPRING.snappy)
Worklet Rules
- No
console.login worklets -- crashes New Architecture UI thread - No closures over JS objects -- pass primitives only
- No async/await -- worklets are synchronous
- No React hooks -- worklets run on UI thread
// ✅ Worklet-safe utility
function clamp(value: number, min: number, max: number): number {
'worklet'
return Math.min(Math.max(value, min), max)
}
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.