---
name: mobile-ui-playbook
description: Use when building or polishing mobile app UI visuals (Flutter, SwiftUI, Jetpack Compose) — before choosing spacing, typography, color, corner radius, elevation, or motion duration; when a screen "looks off", feels cluttered, cheap, or inconsistent; when reviewing touch targets, contrast ratio, Dynamic Type, text overflow, or dark mode; also when hard-coded colors/paddings spread across widgets, or every new screen re-invents its own styling.
---

> 🌐 [繁體中文（canonical）](https://github.com/tienenwu/fables/blob/main/mobile-ui/SKILL.md) · English mirror

# Mobile UI Aesthetics Judgment Handbook

"Looks good" is not mystical taste — it is the byproduct of four things: consistency, hierarchy, density, and contrast. This handbook turns them into adjudicable numbers and criteria.

## Core principles

1. **Beauty is a byproduct of consistency**: tokens (spacing/type/color/radius) come before screens — screens only consume tokens, never invent values; every "tweak it locally just this once" is borrowing at loan-shark rates.
2. **A green light under light mode + default font size + big screen + short data counts for nothing**: dark mode, enlarged text, small physical screens, and long strings / real data are four independent verification axes — any one of them alone can break your UI.
3. **Hierarchy is expressed through size, weight, lightness difference, and position — not decoration**: shadows, gradients, and dividers are the last 10% of polish, not a remedy for unclear hierarchy.
4. **Anything tappable must be big enough and look tappable**: touch targets ≥44×44pt (iOS) / 48×48dp (Android); interactive elements must be visibly distinguishable from plain text.
5. **Motion is the narration of state change**: appearing/disappearing/moving elements need transitions (small components 100–200ms, screen transitions 250–350ms); beyond 500ms users feel "laggy", not "fancy".

## Task triage

| Situation | Path | Read first |
|------|------|------|
| Starting a new screen | Confirm spacing/color/type tokens exist, then lay out | references/design-tokens.md |
| Choosing font size, weight, line height | Follow the type scale criteria; ≤4 sizes per screen | references/design-tokens.md §Type |
| Picking colors, building dark mode | Semantic color roles only, never raw hex | references/design-tokens.md §Color |
| Screen "looks off" but can't say why | Run the five-step diagnosis: alignment→spacing→hierarchy→color→density | references/layout-hierarchy.md §Diagnosis |
| Layout, alignment, information density | Single leading edge + 4/8 grid | references/layout-hierarchy.md |
| Adding motion/transitions | Duration and easing ranges | references/layout-hierarchy.md §Motion |
| UI done, ready to ship | Verify all four axes + extreme data, item by item | references/release-checklist.md |

## Red lines (absolutely forbidden)

- **Never hard-code color values, font sizes, or spacing numbers inside widgets/views** — dark mode and redesigns collapse everything; all values go through theme/tokens.
- **Never ship touch targets smaller than 44×44pt / 48×48dp** — mis-taps and missed taps are the most direct source of "this app feels cheap"; visuals may shrink, hit areas may not.
- **Never ship body text below 4.5:1 contrast (3:1 for large text, WCAG AA)** — low contrast is simply unreadable in outdoor sunlight; "that's the gray in the mockup" is not a reason.
- **Never build dark mode by inverting the light theme color-by-color** — dark mode is a re-mapping of semantic roles (surfaces lighten to express elevation, colors desaturate), not an invert.
- **Never hard-position with fixed widths/heights copied off the mockup** — one long username, one German label, or 130% text scaling will break it; always flexible layout + extreme-data verification.
- **Never introduce a 3rd accent color or a 4th corner-radius step on one screen** — when tempted, adjudicate at the token layer; no inventing values on the spot.
- **Never declare UI done after verifying only light mode + default font size + a big simulator screen** — the four axes are independent failure domains with zero evidential overlap.

## Failure signals (turn back, don't retry)

| Symptom | Usually means | Fall back to |
|------|--------|------|
| Every new screen re-decides its padding numbers | Missing spacing token scale | Define the 4/8 scale at the token layer, snap everything |
| Dark mode full of unreadable or glaring elements | Hard-coded colors, no semantic roles | Rebuild the color layer, don't patch spot by spot |
| Layout breaks on language switch or real data | Fixed-size thinking | Flexible layout + re-verify with extreme data |
| "Just a bit more shadow will fix it" for the 3rd time | A hierarchy-structure problem, not missing decoration | Size/weight/spacing hierarchy design |
| Spacing micro-tweaks oscillating back and forth | No grid baseline, aligning by feel | Snap everything to the 4/8 grid first |
| Fix this screen, that screen drifts again | Styles scattered, no single source of truth | theme/token single source |

## References index

- `references/design-tokens.md` — spacing scale, type scale, semantic color, dark mode, radius/elevation step counts, machine-enforcing tokens. Read before laying anything out.
- `references/layout-hierarchy.md` — alignment, visual hierarchy, density, touch targets, motion durations, the five-step "looks off" diagnosis. Read when a screen feels wrong.
- `references/release-checklist.md` — pre-ship UI checks: four-axis verification, extreme data, contrast and touch-target audits. Tick through before shipping.
- `references/test-scenarios.md` — judgment quiz set to verify a successor model follows the criteria. Not for the model currently executing tasks.
