Agent Skills
Discover and share powerful Agent Skills for AI assistants
react-native-design - Agent Skill - Agent Skills
Home/ Skills / react-native-design Master React Native styling, navigation, and Reanimated animations for cross-platform mobile development. Use when building React Native apps, implementing navigation patterns, or creating performant animations.
Use the skills CLI to install this skill with one command. Auto-detects all installed AI assistants.
Method 1 - skills CLI
npx skills i wshobson/agents/plugins/ui-design/skills/react-native-design CopyMethod 2 - openskills (supports sync & update)
npx openskills install wshobson/agents CopyAuto-detects Claude Code, Cursor, Codex CLI, Gemini CLI, and more. One install, works everywhere.
Installation Path
Download and extract to one of the following locations:
Claude Code Cursor OpenCode Gemini CLI Codex CLI
~/.claude/skills/react-native-design/ Back No setup needed. Let our cloud agents run this skill for you.
Select Model
Claude Haiku 4.5 $0.10 Claude Sonnet 4.5 $0.20 Claude Opus 4.5 $0.50 Claude Sonnet 4.5 $0.20 /task
Best for coding tasks
Try NowEnvironment setup included
React Native Design
Master React Native styling patterns, React Navigation, and Reanimated 3 to build performant, cross-platform mobile applications with native-quality user experiences.
When to Use This Skill
Building cross-platform mobile apps with React Native
Implementing navigation with React Navigation 6+
Creating performant animations with Reanimated 3
Styling components with StyleSheet and styled-components
Building responsive layouts for different screen sizes
Implementing platform-specific designs (iOS/Android)
Creating gesture-driven interactions with Gesture Handler
Optimizing React Native performance
Core Concepts
1. StyleSheet and Styling
Basic StyleSheet:
import { StyleSheet, View, Text } from 'react-native' ;
const styles = StyleSheet. create ({
container: {
flex: 1 ,
padding: 16 ,
backgroundColor: '#ffffff' ,
},
title: {
fontSize: 24 ,
fontWeight: '600' ,
color: '#1a1a1a' ,
marginBottom: 8 ,
},
subtitle: {
fontSize: 16 ,
color: '#666666' ,
lineHeight: 24 ,
},
});
function Card () {
return (
< View style = {styles.container} >
< Text style = {styles.title} > Title </ Text >
< Text style = {styles.subtitle} > Subtitle text </ Text >
</ View >
);
}
Dynamic Styles:
interface CardProps {
variant : 'primary' | 'secondary' ;
disabled ?: boolean ;
}
function Card ({ variant , disabled } : CardProps ) {
return (
< View style =
2. Flexbox Layout
Row and Column Layouts:
const styles = StyleSheet. create ({
// Vertical stack (column)
column: {
flexDirection: "column" ,
gap: 12 ,
},
// Horizontal stack (row)
row: {
flexDirection: "row" ,
alignItems: "center" ,
gap: 8 ,
},
3. React Navigation Setup
Stack Navigator:
import { NavigationContainer } from '@react-navigation/native' ;
import { createNativeStackNavigator } from '@react-navigation/native-stack' ;
type RootStackParamList = {
Home : undefined ;
Detail : { itemId
Tab Navigator:
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' ;
import { Ionicons } from '@expo/vector-icons' ;
type TabParamList = {
Home : undefined ;
Search : undefined ;
4. Reanimated 3 Basics
Animated Values:
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
withTiming,
} from 'react-native-reanimated' ;
function AnimatedBox () {
const scale = useSharedValue ( 1 );
const opacity = useSharedValue ( 1 );
Gesture Handler Integration:
import { Gesture, GestureDetector } from 'react-native-gesture-handler' ;
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated' ;
function DraggableCard () {
const translateX = useSharedValue ( 0
import { Platform, StyleSheet } from "react-native" ;
const styles = StyleSheet. create ({
container: {
padding: 16 ,
... Platform. select ({
ios: {
shadowColor: "#000" ,
shadowOffset: { width: 0 , height: 2 },
Quick Start Component
import React from 'react' ;
import {
View,
Text,
StyleSheet,
Pressable,
Image,
}
Best Practices
Use TypeScript : Define navigation and prop types for type safety
Memoize Components : Use React.memo and useCallback to prevent unnecessary rerenders
Run Animations on UI Thread : Use Reanimated worklets for 60fps animations
Avoid Inline Styles : Use StyleSheet.create for performance
Handle Safe Areas : Use SafeAreaView or useSafeAreaInsets
Test on Real Devices : Simulator/emulator performance differs from real devices
Use FlatList for Lists : Never use ScrollView with map for long lists
Platform-Specific Code : Use Platform.select for iOS/Android differences
Common Issues
Gesture Conflicts : Wrap gestures with GestureDetector and use simultaneousHandlers
Navigation Type Errors : Define ParamList types for all navigators
Animation Jank : Move animations to UI thread with runOnUI worklets
Memory Leaks : Cancel animations and cleanup in useEffect
Font Loading : Use expo-font or react-native-asset for custom fonts
Safe Area Issues : Test on notched devices (iPhone, Android with cutouts)
Resources
{[
styles.card,
variant === 'primary' ? styles.primary : styles.secondary,
disabled && styles.disabled,
]}>
<Text style={styles.text}>Content</Text>
</View>
);
}
const styles = StyleSheet.create({
card: {
padding: 16 ,
borderRadius: 12 ,
},
primary: {
backgroundColor: '#6366f1' ,
},
secondary: {
backgroundColor: '#f3f4f6' ,
borderWidth: 1 ,
borderColor: '#e5e7eb' ,
},
disabled: {
opacity: 0.5 ,
},
text: {
fontSize: 16 ,
},
});
// Space between items
spaceBetween: {
flexDirection: "row" ,
justifyContent: "space-between" ,
alignItems: "center" ,
},
// Centered content
centered: {
flex: 1 ,
justifyContent: "center" ,
alignItems: "center" ,
},
// Fill remaining space
fill: {
flex: 1 ,
},
});
:
string
};
Settings : undefined ;
};
const Stack = createNativeStackNavigator < RootStackParamList >();
function AppNavigator () {
return (
< NavigationContainer >
< Stack.Navigator
initialRouteName = "Home"
screenOptions = {{
headerStyle : { backgroundColor : '#6366f1' },
headerTintColor : '#ffffff' ,
headerTitleStyle : { fontWeight : '600' },
}}
>
< Stack.Screen
name = "Home"
component = {HomeScreen}
options = {{ title : 'Home' }}
/>
< Stack.Screen
name = "Detail"
component = {DetailScreen}
options = {({ route }) => ({
title : `Item ${ route . params . itemId }` ,
})}
/>
< Stack.Screen name = "Settings" component = {SettingsScreen} />
</ Stack.Navigator >
</ NavigationContainer >
);
}
Profile
:
undefined
;
};
const Tab = createBottomTabNavigator < TabParamList >();
function TabNavigator () {
return (
< Tab.Navigator
screenOptions = {({ route }) => ({
tabBarIcon : ({ focused , color , size }) => {
const icons : Record < string , keyof typeof Ionicons.glyphMap> = {
Home: focused ? 'home' : 'home-outline' ,
Search: focused ? 'search' : 'search-outline' ,
Profile: focused ? 'person' : 'person-outline' ,
};
return < Ionicons name ={ icons [route.name]} size ={ size } color ={ color } />;
},
tabBarActiveTintColor : '#6366f1' ,
tabBarInactiveTintColor : '#9ca3af' ,
})}
>
< Tab.Screen name = "Home" component = {HomeScreen} />
< Tab.Screen name = "Search" component = {SearchScreen} />
< Tab.Screen name = "Profile" component = {ProfileScreen} />
</ Tab.Navigator >
);
}
const animatedStyle = useAnimatedStyle (() => ({
transform: [{ scale: scale.value }],
opacity: opacity.value,
}));
const handlePress = () => {
scale.value = withSpring ( 1.2 , {}, () => {
scale.value = withSpring ( 1 );
});
};
return (
< Pressable onPress = {handlePress} >
< Animated.View style = {[styles.box, animatedStyle]} />
</Pressable>
);
}
);
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.card, animatedStyle]}>
<Text>Drag me!</Text>
</Animated.View>
</GestureDetector>
);
}
shadowOpacity: 0.1 ,
shadowRadius: 4 ,
},
android: {
elevation: 4 ,
},
}),
},
text: {
fontFamily: Platform. OS === "ios" ? "SF Pro Text" : "Roboto" ,
fontSize: 16 ,
},
});
// Platform-specific components
import { Platform } from "react-native" ;
const StatusBarHeight = Platform. OS === "ios" ? 44 : 0 ;
from
'react-native'
;
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated' ;
interface ItemCardProps {
title : string ;
subtitle : string ;
imageUrl : string ;
onPress : () => void ;
}
const AnimatedPressable = Animated. createAnimatedComponent (Pressable);
export function ItemCard ({ title , subtitle , imageUrl , onPress } : ItemCardProps ) {
const scale = useSharedValue ( 1 );
const animatedStyle = useAnimatedStyle (() => ({
transform: [{ scale: scale.value }],
}));
return (
< AnimatedPressable
style = {[styles.card, animatedStyle]}
onPress={onPress}
onPressIn={() => { scale.value = withSpring(0.97); }}
onPressOut={() => { scale.value = withSpring(1); }}
>
<Image source={{ uri: imageUrl }} style = {styles.image} />
< View style = {styles.content} >
< Text style = {styles.title} numberOfLines = { 1 } >
{ title }
</ Text >
< Text style = {styles.subtitle} numberOfLines = { 2 } >
{ subtitle }
</ Text >
</ View >
</ AnimatedPressable >
);
}
const styles = StyleSheet. create ({
card: {
backgroundColor: '#ffffff' ,
borderRadius: 16 ,
overflow: 'hidden' ,
shadowColor: '#000' ,
shadowOffset: { width: 0 , height: 2 },
shadowOpacity: 0.1 ,
shadowRadius: 8 ,
elevation: 4 ,
},
image: {
width: '100%' ,
height: 160 ,
backgroundColor: '#f3f4f6' ,
},
content: {
padding: 16 ,
gap: 4 ,
},
title: {
fontSize: 18 ,
fontWeight: '600' ,
color: '#1f2937' ,
},
subtitle: {
fontSize: 14 ,
color: '#6b7280' ,
lineHeight: 20 ,
},
});