How to add animations to your NativeBase App

The distinction between a quality application and an exceptional one often comes down to thoughtful interaction design. One element that users consistently notice and remember is animation. This guide demonstrates how to enhance a NativeBase application using Reanimated to create engaging animations.
What are We Creating
The tutorial walks through building a Todo application enriched with three key animations:
- Button rotation effect triggered on interaction
- Background color transitions when tasks are marked complete
- Swiping gesture to remove items from the list
Implementing Individual Animations
Rotation
The rotation animation uses shared values and derived values to synchronize animation state:
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
useDerivedValue,
interpolate,
withRepeat,
} from "react-native-reanimated";
const animation = useSharedValue(0);
const rotation = useDerivedValue(() => {
return interpolate(animation.value, [0, 360], [0, 360]);
});
const buttonRotation = useAnimatedStyle(() => {
return {
transform: [
{
rotate: rotation.value + "deg",
},
],
};
});
const startAnimation = () => {
animation.value = withRepeat(
withTiming(30, {
duration: 400,
}),
2,
true
);
};
// JSX for button
<TouchableWithoutFeedback
onPress={() => {
if (inputValue) addItem(inputValue);
setInputValue("");
}}
onPressIn={startAnimation}
>
<Animated.View
style={[
{
height: 50,
width: 100,
backgroundColor: colors["primary"][700],
borderRadius: 3,
alignItems: "center",
justifyContent: "center",
paddingHorizontal: 12,
},
buttonRotation,
]}
>
<Text
color="white"
textAlign="center"
fontSize="md"
justifyContent="center"
>
Add Task
</Text>
</Animated.View>
</TouchableWithoutFeedback>The useSharedValue hook bridges the React Native UI thread and animation thread. The useDerivedValue hook transforms shared values, while useAnimatedStyle connects these values to view properties.
Changing Background Color on Click
This animation signals task completion through color transitions:
const { colors } = useTheme();
const progress = useDerivedValue(() => {
return props.item.isCompleted
? withTiming(1, { duration: 2000 })
: withTiming(0, { duration: 2000 });
});
const rContainreStyle = useAnimatedStyle(() => {
const backgroundColor = interpolateColor(
progress.value,
[0, 1],
["white", colors["muted"][100]]
);
return {
backgroundColor,
};
});
// JSX
<Pressable
onPress={() => {
props.handleStatusChange(props.itemI);
}}
>
<PanGestureHandler onGestureEvent={gestureMethod}>
<Animated.View style={[styles.containreStyle, rContainreStyle]}>
<Text fontSize="lg" px={6} color="coolGray.800">
{props.item.title}
</Text>
</Animated.View>
</PanGestureHandler>
</Pressable>The useTheme hook from NativeBase integrates with the theming system for consistent color management.
Removing the Card
Swipe gestures enable smooth item removal:
import { PanGestureHandler } from "react-native-gesture-handler";
const SCREENWIDTH = Dimensions.get("window").width;
const TRANSLATEXTHRESHOLD = -SCREENWIDTH * 0.34;
const translateX = useSharedValue(0);
const MARGIN = useSharedValue(10);
const CONTAINERHEIGHT = useSharedValue(70);
const OPACITY = useSharedValue(1);
const gestureMethod = useAnimatedGestureHandler({
onStart: (event, ctx) => {},
onActive: (event, ctx) => {
translateX.value = event.translationX;
},
onEnd: (event, ctx) => {
const isDismissed = translateX.value < TRANSLATEXTHRESHOLD;
if (isDismissed) {
translateX.value = withTiming(-SCREENWIDTH);
CONTAINERHEIGHT.value = withTiming(0);
MARGIN.value = withTiming(0);
OPACITY.value = withTiming(0);
} else {
translateX.value = withTiming(0);
}
},
});
const rContainreStyle = useAnimatedStyle(() => {
const backgroundColor = interpolateColor(
progress.value,
[0, 1],
["white", colors["muted"][100]]
);
return {
transform: [{ translateX: translateX.value }],
height: CONTAINERHEIGHT.value,
opacity: OPACITY.value,
marginVertical: MARGIN.value,
backgroundColor,
};
});
// JSX
<Pressable
onPress={() => {
props.handleStatusChange(props.itemI);
}}
>
<PanGestureHandler onGestureEvent={gestureMethod}>
<Animated.View style={[styles.containreStyle, rContainreStyle]}>
<Text fontSize="lg" px={6} color="coolGray.800">
{props.item.title}
</Text>
</Animated.View>
</PanGestureHandler>
</Pressable>The PanGestureHandler captures touch events and animates multiple properties — translateX, marginVertical, opacity, and height — based on swipe distance.
Conclusion
Animation significantly amplifies user experience across applications. Animation plays a very pivotal role in enhancing the overall user experience of any application. React Native Reanimated combined with NativeBase's component library simplifies implementation while reducing code complexity. Even straightforward apps like todo lists transform into delightful experiences through thoughtful animation design.