mobile-ui · git:20261029.1aa6bef · 2026-10-29 · sha256 6250bdd590bd45b7

mobile-ui git:20261029.1aa6befA

Immutable. This exact content never changes and is served at /api/v1/blob/6250bdd590bd45b7.

---
description: Native mobile UI/UX craftsmanship, kinetic motion, and tactile engineering skill for iOS (SwiftUI/HIG 18/19), Android (Material 3 Expressive/Jetpack Compose), React Native, and Flutter.
globs: *
alwaysApply: false
---

# Mobile UI/UX Craftsmanship & Native Engineering

The `mobile-ui` skill enforces ultra-premium craftsmanship across native iOS, Android, and cross-platform mobile applications. It replaces stiff layouts and generic web-wrapped interfaces with fluid spring physics, continuous spatial layout morphing, tactile haptics, and strict touch ergonomics.

---

## 1. Quick Navigation & Progressive Disclosure

| Resource Type | Document | Description |
| :--- | :--- | :--- |
| **Reference** | [references/apple-hig-and-material3.md](references/apple-hig-and-material3.md) | Apple HIG 44pt touch targets, Material 3 48dp metrics, dynamic type, safe areas. |
| **Reference** | [references/native-motion-and-gestures.md](references/native-motion-and-gestures.md) | Damped spring physics, matchedGeometryEffect, tactile haptic feedback levels. |
| **Utility** | [scripts/verify_mobile_ui_hygiene.py](scripts/verify_mobile_ui_hygiene.py) | Audits mobile code for missing safe area wrappers, hardcoded touch target violations, and linear animations. |

---

## 2. Apple iOS 18/19 HIG & SwiftUI Craftsmanship

### Spatial Layout Morphing (`matchedGeometryEffect`)
Eliminate jarring navigation pushes and abrupt modal takeovers. Coordinate seamless geometry morphs between compact card surfaces and fullscreen viewports:
```swift
struct FeedCardView: View {
    let item: FeedItem
    var namespace: Namespace.ID
    @Binding var selectedID: String?

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Image(item.heroImage)
                .matchedGeometryEffect(id: "image_\(item.id)", in: namespace)
                .frame(maxWidth: .infinity, maxHeight: 240)
                .clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))

            Text(item.title)
                .matchedGeometryEffect(id: "title_\(item.id)", in: namespace)
                .font(.system(.headline, design: .rounded))
        }
        .padding(16)
        .background(.ultraThinMaterial)
        .clipShape(RoundedRectangle(cornerRadius: 24, style: .continuous))
        .overlay(
            RoundedRectangle(cornerRadius: 24, style: .continuous)
                .stroke(Color.white.opacity(0.12), lineWidth: 1) // 1px specular top highlight
        )
    }
}
```

### Apple Harmonic Spring Physics
Prohibit linear ease-in/ease-out curves. Calibrate physical mass-spring-damper parameters:
- **Default Interactive Springs**: `response: 0.32s`, `dampingFraction: 0.72`, `blendDuration: 0s`.
- **Bouncy Confirmation Pop**: `response: 0.28s`, `dampingFraction: 0.64`.
- **Smooth Sheet Retract**: `response: 0.42s`, `dampingFraction: 0.82`.

### Cupertino Materials & Specular Lighting
- Layer translucency using `.background(.ultraThinMaterial)`.
- Enforce continuous Apple squircles: `RoundedRectangle(cornerRadius: 24, style: .continuous)`.
- Apply a single-zenith top specular hairline: 1px border with `Color.white.opacity(0.12)` in dark mode to simulate physical Fresnel reflection.

### Sensory & Tactile Cues (Haptics)
- **State Toggles & Card Expansion**:
  ```swift
  let generator = UIImpactFeedbackGenerator(style: .medium)
  generator.prepare()
  generator.impactOccurred()
  ```
- **Discrete Rotary Detents**: Enforce `CoreHaptics` (`CHHapticEngine`) or `UISelectionFeedbackGenerator` on drag thresholds and wheel scrubbing.

---

## 2. Android Material 3 Expressive & Jetpack Compose

### Lookahead Bounds Mapping (`SharedTransitionLayout`)
Leverage Compose's `LookaheadScope` to compute destination bounds ahead of time, decoupling measurement from drawing to guarantee zero dropped frames:
```kotlin
@Composable
fun SharedElementFeedCard(
    item: FeedItem,
    sharedTransitionScope: SharedTransitionScope,
    animatedVisibilityScope: AnimatedVisibilityScope
) {
    with(sharedTransitionScope) {
        Surface(
            shape = RoundedCornerShape(24.dp),
            tonalElevation = 2.dp,
            modifier = Modifier
                .sharedBounds(
                    rememberSharedContentState(key = "card_${item.id}"),
                    animatedVisibilityScope = animatedVisibilityScope,
                    boundsTransform = { _, _ ->
                        spring(
                            dampingFraction = 0.78f,
                            stiffness = Spring.StiffnessMediumLow
                        )
                    }
                )
        ) {
            // Card Content
        }
    }
}
```

### Predictive Back Gesture Navigation
Support Android 14+ Predictive Back with real-time gesture feedback:
```kotlin
PredictiveBackHandler { progress ->
    try {
        progress.collect { backEvent ->
            // Interpolate scale down to 0.92f and soften alpha during gesture progress
            val scale = lerp(1f, 0.92f, backEvent.progress)
            val cornerRadius = lerp(0.dp, 32.dp, backEvent.progress)
            currentSheetScale = scale
            currentSheetCorners = cornerRadius
        }
        navigator.popBackStack()
    } catch (e: CancellationException) {
        // User aborted swipe: spring back smoothly to 1.0f
        resetSheetPhysics()
    }
}
```

### Edge-to-Edge System Inset Geometry
Enforce seamless edge-to-edge drawing:
- Bind window insets via `WindowInsets.systemBars.asPaddingValues()`.
- Dynamically absorb virtual keyboards using `Modifier.imePadding()`.

---

## 3. Kinetic Typography & Touch Ergonomics

### Kinetic Variable Fonts & Tabular Numerals
- Variable axes (`wght`, `opsz`, `wdth`): Dynamically interpolate font weight (`wght` 300 $\rightarrow$ 700) during touch drag or pull-to-refresh.
- Tabular figures (`tnum`, `zero`): Always format numerical counters, stock tickers, and stopwatch readouts with monospaced numbers to eliminate horizontal layout jitter.

### Touch Target & Ergonomics Matrix
- **iOS Minimum**: `44x44 pt` interactive touch bounds.
- **Android Minimum**: `48x48 dp` interactive touch bounds.
- **Thumb Zone Distribution**: Place primary interactive triggers (tabs, primary action buttons, FABs) within the bottom 60% of the display viewport.
- **Anti-Trap Guardrail**: Strictly prohibit hardcoded viewport widths (`width: 375`, `width: 414px`). Always anchor layouts to relative safe areas and dynamic flex/grid constraints.

---

## 4. Cross-Platform Guidelines (React Native & Flutter)

### React Native / Expo
- Execute all touch-driven spring gestures on the UI thread via `react-native-reanimated` worklets (`withSpring({ damping: 15, stiffness: 120 })`) and `react-native-gesture-handler`.
- Always wrap screen roots in `<SafeAreaProvider>` and `<SafeAreaView edges={['top', 'bottom']}>`.

### Flutter
- Guarantee 120Hz compositor stability on the **Impeller** rendering engine.
- Implement `Hero` widgets using `MaterialRectArcTween` for natural curved flight paths.
- Bind haptics via `HapticFeedback.lightImpact()` on drag thresholds and sheet snap points.