reanimated-patterns

Reanimated Patterns Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "reanimated-patterns" with this command: npx skills add ivantorresedge/molcajete.ai/ivantorresedge-molcajete-ai-reanimated-patterns

Reanimated Patterns Skill

This skill covers React Native Reanimated for performant animations.

When to Use

Use this skill when:

  • Implementing smooth animations

  • Gesture-based interactions

  • Complex animation sequences

  • Performance-critical animations

Core Principle

UI THREAD ANIMATIONS - Reanimated runs animations on the UI thread for 60fps.

Installation

npx expo install react-native-reanimated

Update babel.config.js:

module.exports = function(api) { api.cache(true); return { presets: ['babel-preset-expo'], plugins: ['react-native-reanimated/plugin'], }; };

Basic Concepts

Shared Values

import { useSharedValue } from 'react-native-reanimated';

// Shared values are synchronized between JS and UI threads const scale = useSharedValue(1); const opacity = useSharedValue(0); const translateX = useSharedValue(0);

// Update shared values scale.value = 2; opacity.value = 1;

Animated Styles

import Animated, { useSharedValue, useAnimatedStyle, } from 'react-native-reanimated';

function AnimatedBox(): React.ReactElement { const scale = useSharedValue(1);

const animatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }], }));

return ( <Animated.View style={[styles.box, animatedStyle]} /> ); }

Animation Functions

withSpring

import { withSpring } from 'react-native-reanimated';

// Spring animation (natural bounce) scale.value = withSpring(2, { damping: 10, stiffness: 100, mass: 1, });

withTiming

import { withTiming, Easing } from 'react-native-reanimated';

// Timed animation opacity.value = withTiming(1, { duration: 300, easing: Easing.bezier(0.25, 0.1, 0.25, 1), });

withDelay

import { withDelay, withSpring } from 'react-native-reanimated';

// Delayed animation scale.value = withDelay(500, withSpring(2));

withSequence

import { withSequence, withTiming } from 'react-native-reanimated';

// Sequential animations scale.value = withSequence( withTiming(1.2, { duration: 100 }), withTiming(0.9, { duration: 100 }), withTiming(1, { duration: 100 }) );

withRepeat

import { withRepeat, withTiming } from 'react-native-reanimated';

// Repeating animation rotation.value = withRepeat( withTiming(360, { duration: 1000 }), -1, // -1 for infinite false // reverse );

Common Animations

Fade In/Out

import Animated, { useSharedValue, useAnimatedStyle, withTiming, } from 'react-native-reanimated';

function FadeView({ visible }: { visible: boolean }): React.ReactElement { const opacity = useSharedValue(0);

useEffect(() => { opacity.value = withTiming(visible ? 1 : 0, { duration: 300 }); }, [visible]);

const animatedStyle = useAnimatedStyle(() => ({ opacity: opacity.value, }));

return ( <Animated.View style={animatedStyle}> {children} </Animated.View> ); }

Scale on Press

function ScaleButton({ onPress, children }: Props): React.ReactElement { const scale = useSharedValue(1);

const animatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }], }));

const handlePressIn = () => { scale.value = withSpring(0.95); };

const handlePressOut = () => { scale.value = withSpring(1); };

return ( <TouchableOpacity onPressIn={handlePressIn} onPressOut={handlePressOut} onPress={onPress} activeOpacity={1} > <Animated.View style={animatedStyle}> {children} </Animated.View> </TouchableOpacity> ); }

Slide In

import { Dimensions } from 'react-native';

const { width } = Dimensions.get('window');

function SlideIn({ visible }: { visible: boolean }): React.ReactElement { const translateX = useSharedValue(width);

useEffect(() => { translateX.value = withSpring(visible ? 0 : width); }, [visible]);

const animatedStyle = useAnimatedStyle(() => ({ transform: [{ translateX: translateX.value }], }));

return ( <Animated.View style={[styles.panel, animatedStyle]}> {children} </Animated.View> ); }

Entering/Exiting Animations

import Animated, { FadeIn, FadeOut, SlideInRight, SlideOutLeft, ZoomIn, BounceIn, } from 'react-native-reanimated';

// Fade <Animated.View entering={FadeIn.duration(300)} exiting={FadeOut.duration(200)}>

// Slide <Animated.View entering={SlideInRight} exiting={SlideOutLeft}>

// Zoom <Animated.View entering={ZoomIn.springify()}>

// Bounce <Animated.View entering={BounceIn.delay(200)}>

// Custom <Animated.View entering={FadeIn.duration(500).delay(100).springify()} exiting={FadeOut.duration(300)}

Layout Animations

import Animated, { Layout } from 'react-native-reanimated';

// Animate layout changes <Animated.View layout={Layout.springify()}> {items.map((item) => ( <Animated.View key={item.id} entering={FadeIn} exiting={FadeOut} layout={Layout} > <Text>{item.name}</Text> </Animated.View> ))} </Animated.View>

Gesture Handler Integration

import { GestureDetector, Gesture } from 'react-native-gesture-handler'; import Animated, { useSharedValue, useAnimatedStyle, withSpring, } from 'react-native-reanimated';

function DraggableBox(): React.ReactElement { const translateX = useSharedValue(0); const translateY = useSharedValue(0);

const gesture = Gesture.Pan() .onUpdate((event) => { translateX.value = event.translationX; translateY.value = event.translationY; }) .onEnd(() => { translateX.value = withSpring(0); translateY.value = withSpring(0); });

const animatedStyle = useAnimatedStyle(() => ({ transform: [ { translateX: translateX.value }, { translateY: translateY.value }, ], }));

return ( <GestureDetector gesture={gesture}> <Animated.View style={[styles.box, animatedStyle]} /> </GestureDetector> ); }

Interpolation

import { interpolate, Extrapolation } from 'react-native-reanimated';

const animatedStyle = useAnimatedStyle(() => { const scale = interpolate( scrollY.value, [0, 100], [1, 0.5], Extrapolation.CLAMP );

const opacity = interpolate( scrollY.value, [0, 50, 100], [1, 0.5, 0] );

return { transform: [{ scale }], opacity, }; });

Worklets

import { runOnJS } from 'react-native-reanimated';

// Call JS function from worklet const updateState = (value: number) => { setState(value); };

const animatedStyle = useAnimatedStyle(() => { if (position.value > 100) { runOnJS(updateState)(position.value); } return { transform: [{ translateX: position.value }] }; });

Notes

  • All animation logic runs on UI thread

  • Use worklets ('worklet' directive) for custom functions

  • Use runOnJS to call JS functions from worklets

  • Test animations on real devices

  • Reanimated is compatible with Expo

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

react-components

No summary provided by upstream source.

Repository SourceNeeds Review
General

software-principles

No summary provided by upstream source.

Repository SourceNeeds Review
General

react-testing

No summary provided by upstream source.

Repository SourceNeeds Review
General

git-committing

No summary provided by upstream source.

Repository SourceNeeds Review