Easy to use declarative transitions and animations for React Native
—
Props-based animation control with extensive configuration options for timing, easing, and behavior. Configure animations through component props for simple, declarative animation management.
Specify animations using the animation prop with built-in names, custom definitions, or registered animations.
interface AnimationProp {
/** Built-in animation name, custom animation object, or registered animation name */
animation?: Animation | string | CustomAnimation;
}
type Animation = 'bounce' | 'flash' | 'jello' | /* ... all built-in animations */;Usage Examples:
// Built-in animation by name
<Animatable.Text animation="bounceIn">
Built-in animation
</Animatable.Text>
// Custom animation object
<Animatable.View animation={{
from: { opacity: 0, scale: 0 },
to: { opacity: 1, scale: 1 }
}}>
Custom animation
</Animatable.View>
// Registered animation by name
<Animatable.View animation="myCustomAnimation">
Registered animation
</Animatable.View>Control animation timing with duration, delay, and iteration properties.
interface TimingProps {
/** Animation duration in milliseconds (default: 1000) */
duration?: number;
/** Delay before animation starts in milliseconds (default: 0) */
delay?: number;
/** Number of times to repeat animation or 'infinite' (default: 1) */
iterationCount?: number | 'infinite';
/** Delay between animation iterations in milliseconds (default: 0) */
iterationDelay?: number;
}Usage Examples:
// Long duration with delay
<Animatable.Text
animation="fadeIn"
duration={2000}
delay={500}
>
Slow fade with delay
</Animatable.Text>
// Infinite looping animation
<Animatable.View
animation="pulse"
iterationCount="infinite"
duration={800}
>
❤️ Infinite pulse
</Animatable.View>
// Multiple iterations with delays
<Animatable.View
animation="bounce"
iterationCount={3}
iterationDelay={1000}
duration={600}
>
Bounce 3 times with pauses
</Animatable.View>Control animation playback direction for more complex animation patterns.
interface DirectionProps {
/** Animation playback direction (default: 'normal') */
direction?: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
}Usage Examples:
// Reverse animation
<Animatable.View
animation="slideInLeft"
direction="reverse"
>
Slides out to the left
</Animatable.View>
// Alternating direction for smooth loops
<Animatable.View
animation="slideInDown"
iterationCount="infinite"
direction="alternate"
duration={1000}
>
Up and down motion
</Animatable.View>
// Alternate reverse starts backwards
<Animatable.View
animation="bounce"
iterationCount={4}
direction="alternate-reverse"
>
Bounce pattern starting reversed
</Animatable.View>Specify easing functions for smooth animation curves.
interface EasingProps {
/** Easing function name or custom function (default: 'ease') */
easing?: Easing;
}
type Easing =
| 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out'
| 'ease-in-cubic' | 'ease-out-cubic' | 'ease-in-out-cubic'
| 'ease-in-circ' | 'ease-out-circ' | 'ease-in-out-circ'
| 'ease-in-expo' | 'ease-out-expo' | 'ease-in-out-expo'
| 'ease-in-quad' | 'ease-out-quad' | 'ease-in-out-quad'
| 'ease-in-quart' | 'ease-out-quart' | 'ease-in-out-quart'
| 'ease-in-quint' | 'ease-out-quint' | 'ease-in-out-quint'
| 'ease-in-sine' | 'ease-out-sine' | 'ease-in-out-sine'
| 'ease-in-back' | 'ease-out-back' | 'ease-in-out-back'
| ((t: number) => number);Usage Examples:
// Smooth ease-out for natural motion
<Animatable.View
animation="slideInUp"
easing="ease-out"
duration={600}
>
Natural slide motion
</Animatable.View>
// Elastic back easing for playful effect
<Animatable.View
animation="zoomIn"
easing="ease-out-back"
duration={800}
>
Elastic zoom effect
</Animatable.View>
// Linear for consistent motion
<Animatable.View
animation="rotate"
easing="linear"
iterationCount="infinite"
duration={2000}
>
Constant rotation speed
</Animatable.View>
// Custom easing function
<Animatable.View
animation="fadeIn"
easing={(t) => t * t * (3 - 2 * t)} // Smoothstep
duration={1000}
>
Custom smoothstep easing
</Animatable.View>Animate style property changes automatically when props change.
interface TransitionProps {
/** Style property names to animate on change */
transition?: string | string[];
}Usage Examples:
// Single property transition
<Animatable.View
transition="backgroundColor"
style={{ backgroundColor: this.state.bgColor }}
duration={300}
>
Background color animates on change
</Animatable.View>
// Multiple property transitions
<Animatable.View
transition={['opacity', 'scale']}
style={{
opacity: this.state.visible ? 1 : 0,
transform: [{ scale: this.state.scale }]
}}
duration={400}
easing="ease-out"
>
Opacity and scale animate together
</Animatable.View>
// Font size transition
<TouchableOpacity onPress={() => this.setState({
fontSize: (this.state.fontSize || 10) + 5
})}>
<Animatable.Text
transition="fontSize"
style={{ fontSize: this.state.fontSize || 10 }}
>
Size me up, Scotty
</Animatable.Text>
</TouchableOpacity>Control animation performance and interaction behavior.
interface PerformanceProps {
/** Use native animation driver for better performance (default: false) */
useNativeDriver?: boolean;
/** Create interaction handle on InteractionManager */
isInteraction?: boolean;
}Usage Examples:
// Native driver for transform animations
<Animatable.View
animation="slideInLeft"
useNativeDriver={true}
duration={300}
>
Hardware-accelerated animation
</Animatable.View>
// Interaction handle for important animations
<Animatable.View
animation="fadeIn"
isInteraction={true}
duration={1000}
>
Blocks interactions until complete
</Animatable.View>
// Note: Native driver limitations
<Animatable.View
animation={{
from: { opacity: 0, translateX: -100 }, // ✅ Works with native driver
to: { opacity: 1, translateX: 0 }
}}
useNativeDriver={true}
/>
<Animatable.View
animation={{
from: { backgroundColor: 'red' }, // ❌ Doesn't work with native driver
to: { backgroundColor: 'blue' }
}}
useNativeDriver={false} // Must use JS driver for colors
/>Respond to animation lifecycle events with callback functions.
interface CallbackProps {
/** Called when animation begins */
onAnimationBegin?: () => void;
/** Called when animation ends with completion state */
onAnimationEnd?: (endState: { finished: boolean }) => void;
/** Called when transition begins for a specific property */
onTransitionBegin?: (property: string) => void;
/** Called when transition ends for a specific property */
onTransitionEnd?: (property: string) => void;
}Usage Examples:
class AnimatedComponent extends Component {
state = { animating: false };
handleAnimationBegin = () => {
console.log('Animation started!');
this.setState({ animating: true });
};
handleAnimationEnd = (endState) => {
console.log('Animation finished:', endState.finished);
this.setState({ animating: false });
if (endState.finished) {
// Animation completed successfully
this.showNextAnimation();
} else {
// Animation was cancelled
this.resetToInitialState();
}
};
handleTransitionBegin = (property) => {
console.log(`Transition started for: ${property}`);
};
handleTransitionEnd = (property) => {
console.log(`Transition ended for: ${property}`);
};
render() {
return (
<Animatable.View
animation="bounceIn"
duration={1000}
onAnimationBegin={this.handleAnimationBegin}
onAnimationEnd={this.handleAnimationEnd}
transition={['opacity', 'scale']}
onTransitionBegin={this.handleTransitionBegin}
onTransitionEnd={this.handleTransitionEnd}
style={{
opacity: this.state.visible ? 1 : 0.5,
transform: [{ scale: this.state.scale || 1 }]
}}
>
<Text>Animated content</Text>
</Animatable.View>
);
}
}interface AnimatableProps {
animation?: Animation | string | CustomAnimation;
duration?: number;
delay?: number;
direction?: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
easing?: Easing;
iterationCount?: number | 'infinite';
iterationDelay?: number;
transition?: string | string[];
useNativeDriver?: boolean;
isInteraction?: boolean;
onAnimationBegin?: () => void;
onAnimationEnd?: (endState: { finished: boolean }) => void;
onTransitionBegin?: (property: string) => void;
onTransitionEnd?: (property: string) => void;
}// Animation based on state
<Animatable.View
animation={this.state.isVisible ? "fadeIn" : "fadeOut"}
duration={300}
>
<Text>Conditional animation</Text>
</Animatable.View>
// Different animations for different states
<Animatable.View
animation={
this.state.loading ? "pulse" :
this.state.error ? "shake" :
this.state.success ? "bounce" : null
}
iterationCount={this.state.loading ? "infinite" : 1}
>
<StatusContent />
</Animatable.View>// Duration based on screen size or user preferences
<Animatable.View
animation="slideInRight"
duration={this.props.reducedMotion ? 100 : 600}
easing={this.props.reducedMotion ? "linear" : "ease-out"}
>
<Content />
</Animatable.View>// Sequential animations with delays
<View>
<Animatable.Text animation="fadeInUp" delay={0} duration={500}>
First line
</Animatable.Text>
<Animatable.Text animation="fadeInUp" delay={200} duration={500}>
Second line
</Animatable.Text>
<Animatable.Text animation="fadeInUp" delay={400} duration={500}>
Third line
</Animatable.Text>
</View>Install with Tessl CLI
npx tessl i tessl/npm-react-native-animatable