Skip to main content

react-native-ui-patterns

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.

跳到安装

来源信息

仓库
paulpas/agent-skill-router
最近来源活动
2026年6月9日 16:28
检测到的 SKILL.md 语言
英语
星标
4
分支
1

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

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)
在 GitHub 查看