Claude
Skills
Sign in
Back

ui-mobile

Included with Lifetime
$97 forever

Mobile UI patterns - React Native, iOS/Android, touch targets

Design

What this skill does


# Mobile UI Design Skill (React Native)


---

## MANDATORY: Mobile Accessibility Standards

**These rules are NON-NEGOTIABLE. Every UI element must pass these checks.**

### 1. Touch Targets (CRITICAL)
```typescript
// MINIMUM 44x44 points for ALL interactive elements
const MINIMUM_TOUCH_SIZE = 44;

// EVERY button, link, icon button must meet this
const styles = StyleSheet.create({
  button: {
    minHeight: MINIMUM_TOUCH_SIZE,
    minWidth: MINIMUM_TOUCH_SIZE,
    paddingVertical: 12,
    paddingHorizontal: 16,
  },
  iconButton: {
    width: MINIMUM_TOUCH_SIZE,
    height: MINIMUM_TOUCH_SIZE,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

// NEVER DO THIS:
style={{ height: 30 }}  // ✗ TOO SMALL
style={{ padding: 4 }}  // ✗ RESULTS IN TINY TARGET
```

### 2. Color Contrast (CRITICAL)
```typescript
// WCAG 2.1 AA: 4.5:1 for text, 3:1 for large text/UI

// SAFE COMBINATIONS:
const colors = {
  // Light mode
  textPrimary: '#000000',     // on white = 21:1 ✓
  textSecondary: '#374151',   // gray-700 on white = 9.2:1 ✓

  // Dark mode
  textPrimaryDark: '#FFFFFF', // on gray-900 = 16:1 ✓
  textSecondaryDark: '#E5E7EB', // gray-200 on gray-900 = 11:1 ✓
};

// FORBIDDEN - FAILS CONTRAST:
// ✗ '#9CA3AF' (gray-400) on white = 2.6:1
// ✗ '#6B7280' (gray-500) on '#111827' = 4.0:1
// ✗ Any text below 4.5:1 ratio
```

### 3. Visibility Rules
```typescript
// ALL BUTTONS MUST HAVE visible boundaries

// PRIMARY: Solid background with contrasting text
<Pressable style={styles.primaryButton}>
  <Text style={{ color: '#FFFFFF' }}>Submit</Text>
</Pressable>

const styles = StyleSheet.create({
  primaryButton: {
    backgroundColor: '#1F2937', // gray-800
    paddingVertical: 16,
    paddingHorizontal: 24,
    borderRadius: 12,
    minHeight: 44,
  },
});

// SECONDARY: Visible background
<Pressable style={styles.secondaryButton}>
  <Text style={{ color: '#1F2937' }}>Cancel</Text>
</Pressable>

const styles = StyleSheet.create({
  secondaryButton: {
    backgroundColor: '#F3F4F6', // gray-100
    minHeight: 44,
  },
});

// GHOST: MUST have visible border
<Pressable style={styles.ghostButton}>
  <Text style={{ color: '#374151' }}>Skip</Text>
</Pressable>

const styles = StyleSheet.create({
  ghostButton: {
    borderWidth: 1,
    borderColor: '#D1D5DB', // gray-300
    minHeight: 44,
  },
});

// NEVER CREATE invisible buttons:
// ✗ backgroundColor: 'transparent' without border
// ✗ Text color matching background
```

### 4. Accessibility Labels (REQUIRED)
```tsx
// EVERY interactive element needs accessibility props

// Buttons
<Pressable
  accessible={true}
  accessibilityRole="button"
  accessibilityLabel="Submit form"
  accessibilityHint="Double tap to submit your information"
>
  <Text>Submit</Text>
</Pressable>

// Icon buttons (NO visible text = MUST have label)
<Pressable
  accessible={true}
  accessibilityRole="button"
  accessibilityLabel="Close menu"
>
  <CloseIcon />
</Pressable>

// Images
<Image
  accessible={true}
  accessibilityRole="image"
  accessibilityLabel="User profile photo"
  source={...}
/>
```

### 5. Focus/Selection States
```tsx
// EVERY Pressable needs visible pressed state
<Pressable
  style={({ pressed }) => [
    styles.button,
    pressed && styles.buttonPressed,
  ]}
>
  {children}
</Pressable>

const styles = StyleSheet.create({
  button: {
    backgroundColor: '#1F2937',
  },
  buttonPressed: {
    opacity: 0.7,
    // OR
    backgroundColor: '#374151',
  },
});
```

---

## Core Philosophy

**Mobile UI is about touch, speed, and focus.** No hover states, smaller screens, thumb-friendly targets. Design for one-handed use and interruption recovery.

## Platform Differences

### iOS vs Android
```typescript
import { Platform } from 'react-native';

// Platform-specific values
const styles = StyleSheet.create({
  shadow: Platform.select({
    ios: {
      shadowColor: '#000',
      shadowOffset: { width: 0, height: 2 },
      shadowOpacity: 0.1,
      shadowRadius: 8,
    },
    android: {
      elevation: 4,
    },
  }),

  // iOS uses SF Pro, Android uses Roboto
  text: {
    fontFamily: Platform.OS === 'ios' ? 'System' : 'Roboto',
  },
});
```

### Design Language
```
iOS (Human Interface Guidelines)
─────────────────────────────────
- Flat design with subtle depth
- SF Symbols for icons
- Large titles (34pt)
- Rounded corners (10-14pt)
- Blue as default tint

Android (Material Design 3)
─────────────────────────────────
- Material You dynamic color
- Outlined/filled icons
- Medium titles (22pt)
- Rounded corners (12-28pt)
- Primary color from theme
```

## Spacing System

### 4px Base Grid
```typescript
// React Native spacing - consistent scale
const spacing = {
  xs: 4,
  sm: 8,
  md: 16,
  lg: 24,
  xl: 32,
  '2xl': 48,
} as const;

// Usage
const styles = StyleSheet.create({
  container: {
    padding: spacing.md,
    gap: spacing.sm,
  },
});
```

### Safe Areas
```tsx
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const Screen = ({ children }) => {
  const insets = useSafeAreaInsets();

  return (
    <View style={{
      flex: 1,
      paddingTop: insets.top,
      paddingBottom: insets.bottom,
      paddingLeft: Math.max(insets.left, 16),
      paddingRight: Math.max(insets.right, 16),
    }}>
      {children}
    </View>
  );
};
```

## Typography

### Type Scale
```typescript
const typography = {
  // Large titles (iOS style)
  largeTitle: {
    fontSize: 34,
    fontWeight: '700' as const,
    letterSpacing: 0.37,
  },

  // Section headers
  title: {
    fontSize: 22,
    fontWeight: '700' as const,
    letterSpacing: 0.35,
  },

  // Card titles
  headline: {
    fontSize: 17,
    fontWeight: '600' as const,
    letterSpacing: -0.41,
  },

  // Body text
  body: {
    fontSize: 17,
    fontWeight: '400' as const,
    letterSpacing: -0.41,
    lineHeight: 22,
  },

  // Secondary text
  callout: {
    fontSize: 16,
    fontWeight: '400' as const,
    letterSpacing: -0.32,
  },

  // Small labels
  caption: {
    fontSize: 12,
    fontWeight: '400' as const,
    letterSpacing: 0,
  },
};
```

## Color System

### Semantic Colors
```typescript
// Use semantic names, not literal colors
const colors = {
  // Backgrounds
  background: '#FFFFFF',
  backgroundSecondary: '#F2F2F7',
  backgroundTertiary: '#FFFFFF',

  // Surfaces
  surface: '#FFFFFF',
  surfaceElevated: '#FFFFFF',

  // Text
  label: '#000000',
  labelSecondary: '#3C3C43', // 60% opacity
  labelTertiary: '#3C3C43',  // 30% opacity

  // Actions
  primary: '#007AFF',
  destructive: '#FF3B30',
  success: '#34C759',
  warning: '#FF9500',

  // Separators
  separator: '#3C3C43', // 29% opacity
  opaqueSeparator: '#C6C6C8',
};

// Dark mode variants
const darkColors = {
  background: '#000000',
  backgroundSecondary: '#1C1C1E',
  label: '#FFFFFF',
  labelSecondary: '#EBEBF5', // 60% opacity
  separator: '#545458',
};
```

### Dynamic Colors (React Native)
```tsx
import { useColorScheme } from 'react-native';

const useColors = () => {
  const scheme = useColorScheme();
  return scheme === 'dark' ? darkColors : colors;
};

// Usage
const MyComponent = () => {
  const colors = useColors();
  return (
    <View style={{ backgroundColor: colors.background }}>
      <Text style={{ color: colors.label }}>Hello</Text>
    </View>
  );
};
```

## Touch Targets

### Minimum Sizes
```typescript
// CRITICAL: Minimum 44pt touch targets
const touchable = {
  minHeight: 44,
  minWidth: 44,
};

// Button with proper sizing
const styles = StyleSheet.create({
  button: {
    minHeight: 44,
    paddingHorizontal: 16,
    paddingVertical: 12,
    justifyContent: 'center',
    alignItems: 'center',
  },

  // Icon button (square)
  iconButton: {
    width: 44,
    height: 44,
    justifyContent: 'center',
    alignItems: 'center',
  },

  // List row
  listRow: {
    minHeight: 44,
    paddingVertical: 12,
    paddingHorizontal: 16,
  },
});
```

### Touch Feedback
```tsx
import { Pressable } from 'react-native';

// iOS-style opacity feedb
Files: 1
Size: 19.3 KB
Complexity: 26/100
Category: Design

Related in Design