Skip to content
Back to skills

React Native Ui Patterns

ASecurity

Implements responsive, accessible, and consistent UI components in React Native using Flexbox layouts, theme systems with dark mode support, platform-specific styling, and safe area handling.

  • 4 stars
  • 0 votes
  • 0 copies
  • 11 views
  • Added June 12, 2026
designgoreactnodegitapiperformancedocumentation

Works with

  • api

Security analysis

A100/100

Scanned June 12, 2026

npx -y skills add paulpas/agent-skill-router --skill react-native-ui-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of React Native Ui Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for React Native Ui Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/paulpas-react-native-ui-patterns/badge)](https://www.skillsdirectory.com/skills/paulpas-react-native-ui-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: react-native-ui-patterns
description: Implements responsive, accessible, and consistent UI components in React Native using Flexbox layouts, theme systems with dark mode support, platform-specific styling, and safe area handling.
license: MIT
compatibility: opencode
archetypes:
  - tactical
  - generation
anti_triggers:
  - brainstorming
  - vague ideation
  - long-form architecture
response_profile:
  verbosity: low
  directive_strength: high
  abstraction_level: operational
metadata:
  version: "1.0.0"
  domain: coding
  triggers: react native ui, react native styling, responsive layout, dark mode, flexbox, safe area, platform specific
  role: implementation
  scope: implementation
  output-format: code
  content-types: [code, guidance, do-dont, examples]
  related-skills: react-native-animation, react-native-navigation, react-native-list-performance
  author: https://github.com/vercel-labs
  source: https://github.com/vercel-labs/agent-skills
---

# React Native UI Patterns

Implements responsive, accessible, and consistent UI in React Native using Flexbox layouts, a theme system with light and dark mode, platform-specific extensions, SafeAreaView for notches, KeyboardAvoidingView for forms, and Dynamic Type support for text accessibility.

## TL;DR Checklist

- [ ] Use Flexbox (flex, flexDirection, alignItems, justifyContent) for all layouts
- [ ] Implement a theme context with light and dark mode color palettes
- [ ] Use SafeAreaView to handle notches, status bars, and home indicators
- [ ] Support Dynamic Type via allowFontScaling with maxFontSizeMultiplier
- [ ] Use useWindowDimensions for responsive breakpoints
- [ ] Use Platform.select for OS-specific styling
- [ ] Ensure touch targets are at least 44pt with adequate hitSlop

---

## When to Use

Use this skill when:

- Building the layout foundation for a new React Native app
- Adding dark mode support to an existing application
- Creating a theme system with consistent spacing, typography, and colors
- Ensuring UI works across iPhone notch, Dynamic Island, and Android status bars
- Building responsive layouts that adapt to tablet and phone screens
- Making forms accessible with keyboard-avoiding behavior
- Implementing platform-specific designs for iOS and Android

---

## When NOT to Use

Avoid this skill for:

- Web-only React projects (use CSS media queries and CSS custom properties)
- Apps that don't need responsive layouts (fixed-size canvas apps)
- Prototypes where a single-platform look is acceptable
- Situations where theming is handled by a third-party UI library

---

## Core Workflow

1. **Set Up Theme System** — Define a theme object with colors, spacing scale, typography, and breakpoints. Provide it via React Context.

2. **Implement Responsive Layouts** — Use Flexbox properties with useWindowDimensions for adaptive breakpoints.

3. **Add Safe Area Support** — Wrap screens with SafeAreaView and configure edges.

4. **Support Dark Mode** — Use useColorScheme() to toggle between light and dark theme palettes.

5. **Handle Platform Differences** — Use Platform.select or platform-specific file extensions (.ios.tsx, .android.tsx).

6. **Add Accessibility** — Enable font scaling with maxFontSizeMultiplier caps, and set hitSlop on small touch targets.

---

## Implementation Patterns

### Pattern 1: Theme System with Dark Mode

```tsx
// ✅ GOOD: Full theme system with light/dark mode
interface Theme {
  colors: {
    background: string;
    surface: string;
    text: string;
    textSecondary: string;
    primary: string;
    border: string;
    error: string;
  };
  spacing: {
    xs: number;
    sm: number;
    md: number;
    lg: number;
    xl: number;
  };
  typography: {
    h1: TextStyle;
    body: TextStyle;
    caption: TextStyle;
  };
}

const lightTheme: Theme = {
  colors: {
    background: '#FFFFFF',
    surface: '#F5F5F5',
    text: '#1A1A1A',
    textSecondary: '#666666',
    primary: '#007AFF',
    border: '#E0E0E0',
    error: '#FF3B30',
  },
  spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 32 },
  typography: {
    h1: { fontSize: 28, fontWeight: '700', lineHeight: 34 },
    body: { fontSize: 16, fontWeight: '400', lineHeight: 22 },
    caption: { fontSize: 12, fontWeight: '400', lineHeight: 16 },
  },
};

const darkTheme: Theme = {
  ...lightTheme,
  colors: {
    background: '#1A1A1A',
    surface: '#2C2C2C',
    text: '#FFFFFF',
    textSecondary: '#AAAAAA',
    primary: '#0A84FF',
    border: '#3A3A3A',
    error: '#FF453A',
  },
};

// Theme context
const ThemeContext = createContext<Theme>(lightTheme);

function ThemeProvider({ children }: { children: React.ReactNode }) {
  const colorScheme = useColorScheme();
  const theme = colorScheme === 'dark' ? darkTheme : lightTheme;

  return (
    <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
  );
}

// Usage in a component
function ThemedCard() {
  const theme = useContext(ThemeContext);

  return (
    <View
      style={{
        backgroundColor: theme.colors.surface,
        padding: theme.spacing.md,
        borderRadius: 12,
      }}
    >
      <Text
        style={[
          theme.typography.body,
          { color: theme.colors.text },
        ]}
      >
        Themed content
      </Text>
    </View>
  );
}
```

### Pattern 2: Flexbox Responsive Layout (BAD vs. GOOD)

```tsx
// ❌ BAD: Hardcoded pixel values — breaks on different screen sizes
function BadLayout() {
  return (
    <View>
      <View style={{ width: 300, height: 200 }}> {/* Fixed width */}
        <Image source={logo} style={{ width: 200, height: 100 }} />
      </View>
      <View style={{ marginLeft: 20 }}>
        <Text style={{ fontSize: 14 }}>Description</Text>
      </View>
    </View>
  );
}
```

```tsx
// ✅ GOOD: Flexbox-based layout that adapts to any screen size
function ResponsiveCard({ item }: { item: CardItem }) {
  const { width } = useWindowDimensions();
  const isTablet = width >= 768;

  return (
    <View style={[styles.card, isTablet && styles.cardTablet]}>
      <Image source={item.image} style={styles.image} />
      <View style={styles.content}>
        <Text style={styles.title} numberOfLines={2}>
          {item.title}
        </Text>
        <Text style={styles.description} numberOfLines={3}>
          {item.description}
        </Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  card: {
    flexDirection: 'row',
    alignItems: 'flex-start',
    padding: 16,
    marginHorizontal: 16,
    marginVertical: 8,
    borderRadius: 12,
    backgroundColor: '#fff',
    // Shadow for iOS
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    // Elevation for Android
    elevation: 3,
  },
  cardTablet: {
    padding: 24,
    marginHorizontal: 48,
  },
  image: {
    width: 80,
    height: 80,
    borderRadius: 8,
  },
  content: {
    flex: 1, // Takes remaining space
    marginLeft: 12,
  },
  title: {
    fontSize: 18,
    fontWeight: '600',
    marginBottom: 4,
  },
  description: {
    fontSize: 14,
    color: '#666',
    lineHeight: 20,
  },
});
```

### Pattern 3: Platform-Specific Styling

```tsx
// ✅ GOOD: Platform.select for OS-specific values
import { Platform, PlatformOSType } from 'react-native';

const SHADOW_STYLES = Platform.select({
  ios: {
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
  },
  android: {
    elevation: 3,
  },
  default: {},
});

// Platform-specific component via file extension:
// Card.ios.tsx
// Card.android.tsx
// These files auto-resolve at build time
```

```tsx
// ✅ GOOD: Helper function for platform-specific values
function getPlatformValue<T>(values: Partial<Record<PlatformOSType, T>>, fallback: T): T {
  return values[Platform.OS] ?? fallback;
}

// Usage
const hitSlop = getPlatformValue(
  { ios: { top: 10, bottom: 10, left: 10, right: 10 } },
  { top: 8, bottom: 8, left: 8, right: 8 }
);
```

### Pattern 4: SafeArea and Keyboard Avoiding

```tsx
// ✅ GOOD: SafeAreaView + KeyboardAvoidingView for form screens
import { SafeAreaView } from 'react-native-safe-area-context';
import { KeyboardAvoidingView, Platform } from 'react-native';

function LoginScreen() {
  return (
    <SafeAreaView edges={['top', 'bottom']} style={styles.safeArea}>
      <KeyboardAvoidingView
        behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
        style={styles.keyboardAvoid}
      >
        <ScrollView
          contentContainerStyle={styles.scrollContent}
          keyboardShouldPersistTaps="handled"
        >
          <Text style={styles.title}>Welcome Back</Text>
          <TextInput
            style={styles.input}
            placeholder="Email"
            autoCapitalize="none"
            keyboardType="email-address"
            autoComplete="email"
          />
          <TextInput
            style={styles.input}
            placeholder="Password"
            secureTextEntry
            autoComplete="password"
          />
          <TouchableOpacity style={styles.button} activeOpacity={0.8}>
            <Text style={styles.buttonText}>Log In</Text>
          </TouchableOpacity>
        </ScrollView>
      </KeyboardAvoidingView>
    </SafeAreaView>
  );
}
```

### Pattern 5: Accessible Touch Targets

```tsx
// ✅ GOOD: Minimum 44pt touch target with hitSlop for close-spaced items
function IconButton({ icon, onPress, label }: IconButtonProps) {
  return (
    <TouchableOpacity
      onPress={onPress}
      hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
      accessibilityLabel={label}
      accessibilityRole="button"
      style={styles.iconButton}
    >
      <Icon name={icon} size={24} />
    </TouchableOpacity>
  );
}

// ✅ GOOD: Dynamic Type support with capped max font size
function AccessibleText({ children, style }: TextProps) {
  return (
    <Text
      style={style}
      allowFontScaling={true}
      maxFontSizeMultiplier={1.5} // Caps at 150% of base size
    >
      {children}
    </Text>
  );
}
```

---

## Constraints

### MUST DO
- Use Flexbox (flex, flexDirection, alignItems, justifyContent) for all layouts — never absolute positioning for page layout
- Support dark mode via `useColorScheme()` or a theme context that toggles color palettes
- Respect safe areas using `SafeAreaView` from react-native-safe-area-context
- Support Dynamic Type with `allowFontScaling={true}` and `maxFontSizeMultiplier={1.5}`
- Use a spacing scale from the theme object — never hardcode pixel values
- Provide `hitSlop` for touch targets smaller than 44pt (minimum recommended size)
- Use `KeyboardAvoidingView` with correct `behavior` prop per platform for form screens

### MUST NOT DO
- Hardcode pixel values for margins, padding, widths, or font sizes — use theme spacing scale
- Ignore safe areas on iPhone X+ or Android devices with display cutouts
- Use fixed widths — prefer flex percentages or the `flex` property
- Forget to set `accessibilityLabel` and `accessibilityRole` on interactive elements
- Use `position: absolute` for regular layout — reserve it for overlay/modal positioning
- Neglect shadow styles on iOS (shadowColor, shadowOffset, shadowOpacity, shadowRadius) or elevation on Android

---

## Related Skills

| Skill | Purpose |
|---|---|
| `react-native-animation` | Animate theme transitions and layout changes |
| `react-native-navigation` | Navigation theming, tab bar styling, screen transitions |
| `react-native-list-performance` | Responsive list item layouts with useWindowDimensions |

---

## Live References

> Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.

- [React Native Flexbox Documentation](https://reactnative.dev/docs/flexbox)
- [React Native useWindowDimensions](https://reactnative.dev/docs/usewindowdimensions)
- [React Native Platform-Specific Code](https://reactnative.dev/docs/platform-specific-code)
- [react-native-safe-area-context](https://github.com/th3rdwave/react-native-safe-area-context)
- [React Native Accessibility Guide](https://reactnative.dev/docs/accessibility)
- [Human Interface Guidelines: Layout](https://developer.apple.com/design/human-interface-guidelines/layout)
- [Material Design 3: Dark Theme](https://m3.material.io/foundations/dark-theme)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…