react-native-design

Cross-platform mobile apps with React Native styling, navigation, and performant Reanimated animations. Covers StyleSheet patterns, dynamic styling, Flexbox layouts, and platform-specific designs for iOS and Android Includes React Navigation 6+ setup for stack and tab navigators with type-safe route definitions Provides Reanimated 3 fundamentals including shared values, animated styles, and Gesture Handler integration for drag interactions Features best practices for performance (memoization, UI thread animations, FlatList usage) and common troubleshooting patterns

INSTALLATION
npx skills add https://github.com/wshobson/agents --skill react-native-design
Run in your project or agent environment. Adjust flags if your CLI version differs.

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 &#x26;&#x26; 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.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)
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card