Agent skill
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.
Install this agent skill to your Project
npx add-skill https://github.com/aiskillstore/marketplace/tree/main/skills/wshobson/react-native-design
SKILL.md
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={[
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,
},
});
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,
},
// 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,
},
});
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: 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>
);
}
Tab Navigator:
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons } from '@expo/vector-icons';
type TabParamList = {
Home: undefined;
Search: undefined;
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>
);
}
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);
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>
);
}
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);
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>
);
}
5. Platform-Specific Styling
import { Platform, StyleSheet } from "react-native";
const styles = StyleSheet.create({
container: {
padding: 16,
...Platform.select({
ios: {
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
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;
Quick Start Component
import React from 'react';
import {
View,
Text,
StyleSheet,
Pressable,
Image,
} 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,
},
});
Best Practices
- Use TypeScript: Define navigation and prop types for type safety
- Memoize Components: Use
React.memoanduseCallbackto 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
SafeAreaVieworuseSafeAreaInsets - 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
GestureDetectorand usesimultaneousHandlers - Navigation Type Errors: Define
ParamListtypes for all navigators - Animation Jank: Move animations to UI thread with
runOnUIworklets - Memory Leaks: Cancel animations and cleanup in useEffect
- Font Loading: Use
expo-fontorreact-native-assetfor custom fonts - Safe Area Issues: Test on notched devices (iPhone, Android with cutouts)
Resources
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
perigon-backend
Perigon ASP.NET Core + EF Core + Aspire conventions
perigon-agent
Pointers for Copilot/agents to apply Perigon conventions
perigon-angular
Angular 21+ standalone/Material/signal conventions for Perigon WebApp
fastapi-mastery
Comprehensive FastAPI development skill covering REST API creation, routing, request/response handling, validation, authentication, database integration, middleware, and deployment. Use when working with FastAPI projects, building APIs, implementing CRUD operations, setting up authentication/authorization, integrating databases (SQL/NoSQL), adding middleware, handling WebSockets, or deploying FastAPI applications. Triggered by requests involving .py files with FastAPI code, API endpoint creation, Pydantic models, or FastAPI-specific features.
context7-efficient
Token-efficient library documentation fetcher using Context7 MCP with 86.8% token savings through intelligent shell pipeline filtering. Fetches code examples, API references, and best practices for JavaScript, Python, Go, Rust, and other libraries. Use when users ask about library documentation, need code examples, want API usage patterns, are learning a new framework, need syntax reference, or troubleshooting with library-specific information. Triggers include questions like "Show me React hooks", "How do I use Prisma", "What's the Next.js routing syntax", or any request for library/framework documentation.
browser-use
Browser automation using Playwright MCP. Navigate websites, fill forms, click elements, take screenshots, and extract data. Use when tasks require web browsing, form submission, web scraping, UI testing, or any browser interaction.
Didn't find tool you were looking for?