Mobile Design Formula (MOBILE APP ONLY)
AUTO-TRIGGER
Invoke lần đầu tiên mỗi session khi:
- User nói: "build app/màn hình/screen/widget Flutter/RN"
- User nói: "thêm/sửa UI mobile/app"
- Agent sắp edit/write file
.dart .swift .kt .java (trong project mobile)
- Agent sắp chạm thư mục
mobile/ lib/ ios/ android/
KHÔNG dùng khi
- Web (React, Next.js, Vue, Svelte, HTML/CSS) → dùng
frontend-design
- Backend — không có UI
Tư duy cốt lõi
Mobile ≠ Web thu nhỏ. Công thức khác hoàn toàn:
|
Web |
Mobile |
| Typography scale |
Dynamic clamp(44-72px) |
Fixed scale (24/20/16/14/12sp) |
| Motion |
Long (1.5-3s entrance) |
Short (200-400ms) — instant feedback |
| Spacing |
py-32 (128px) section |
16dp/24dp base unit |
| Touch target |
N/A |
Min 44pt iOS / 48dp Android |
| Navigation |
Scroll/link |
Tab bar / bottom nav / stack |
| Aesthetic |
Can be experimental |
Platform conventions (Material 3 / HIG) |
| Performance |
Depends on device |
Critical — 60fps mandatory |
Platform conventions (BẮT BUỘC tuân thủ)
Flutter
- Material 3 (Android) / Cupertino (iOS) — detect platform, render đúng widget
- Dùng
Theme.of(context) thay hardcode color
MediaQuery cho responsive, SafeArea cho notch
Hero animation cho screen transition
- State: Riverpod / BLoC, KHÔNG setState cho state phức tạp
React Native
Platform.OS check để render iOS/Android khác nhau
SafeAreaView (react-native-safe-area-context)
react-native-reanimated cho animation (60fps), KHÔNG Animated API cũ
- Navigation: React Navigation (stack/tab/drawer)
SwiftUI / Jetpack Compose
- Follow Apple HIG / Material 3 spec 100%
- System fonts, system colors (dark mode auto)
- Accessibility-first: VoiceOver / TalkBack
Design tokens (cho Commerce mobile app)
// Flutter example — lib/core/theme.dart
class AppColors {
// Light mode
static const bgPrimary = Color(0xFFF5F5F7);
static const bgCard = Color(0xFFFFFFFF);
static const textPrimary = Color(0xFF1A1A1A);
static const textMuted = Color(0xFF666666);
static const accent = Color(0xFF007AFF); // iOS blue — hoặc Material 3 seed
static const danger = Color(0xFFFF3B30);
static const border = Color(0xFFE5E5E7);
// Dark mode
static const bgPrimaryDark = Color(0xFF000000);
static const bgCardDark = Color(0xFF1C1C1E);
static const textPrimaryDark = Color(0xFFF5F0EB);
// ...
}
class AppSpacing {
static const xs = 4.0; // 4dp
static const sm = 8.0;
static const md = 16.0; // base
static const lg = 24.0;
static const xl = 32.0;
static const xxl = 48.0;
}
class AppTypography {
static const display = TextStyle(fontSize: 32, fontWeight: FontWeight.w700, height: 1.2);
static const title = TextStyle(fontSize: 24, fontWeight: FontWeight.w600, height: 1.25);
static const headline = TextStyle(fontSize: 20, fontWeight: FontWeight.w600);
static const body = TextStyle(fontSize: 16, fontWeight: FontWeight.w400, height: 1.5);
static const bodySmall = TextStyle(fontSize: 14, fontWeight: FontWeight.w400, height: 1.4);
static const caption = TextStyle(fontSize: 12, fontWeight: FontWeight.w500, letterSpacing: 0.5);
}
class AppRadius {
static const sm = 8.0;
static const md = 12.0;
static const lg = 16.0; // card/modal default
static const xl = 24.0;
static const pill = 999.0;
}
Mobile UX rules
- Touch target ≥ 44pt (iOS) / 48dp (Android) — không được nhỏ hơn
- Feedback trong 100ms — haptic, visual press state
- Loading ≤ 300ms → không cần indicator (user không kịp nhận ra)
- Loading > 1s → phải có skeleton/shimmer (không spinner thuần)
- Gesture natural — swipe back iOS, pull-to-refresh, long-press menu
- Offline-first — cache data local, sync background (quan trọng với Commerce VN)
- Keyboard awareness — scroll content lên khi keyboard mở, don't hide inputs
- Error recovery — mọi error phải có CTA retry, không dead-end
Anti-patterns
| Sai |
Đúng |
| Fixed pixel height |
MediaQuery.of(context).size.height * x |
| setState cho toàn screen |
Riverpod selector / BLoC state slice |
print() debug |
debugPrint() hoặc logger package |
| Hardcode color |
Theme.of(context).colorScheme.xxx |
| Blocking main thread |
compute() cho heavy work |
| Image.network không cache |
cached_network_image package |
setState(() {}) sau async gap không check mounted |
if (!mounted) return; |
| Web design system (liquid glass, GSAP) |
Platform conventions — Material/Cupertino |
Self-check trước khi ship mobile UI
□ Touch targets ≥ 44pt/48dp?
□ Theme tokens dùng nhất quán (không hardcode color/spacing)?
□ Dark mode support?
□ Loading state (skeleton, không spinner thuần)?
□ Empty state có illustration + CTA?
□ Error state có retry button?
□ Keyboard handling (scroll, dismiss, action button)?
□ SafeArea cho notch/home indicator?
□ Accessibility (semanticsLabel, contrast ≥ 4.5:1)?
□ 60fps khi scroll list dài? (flutter profile mode test)
□ Offline graceful (cached data + sync indicator)?
□ Haptic feedback trên action quan trọng?
TODO — khi Commerce bắt đầu build mobile
Hiện chưa có project mobile nào của anh active. Khi bắt đầu Flutter admin app, expand skill này với:
- Riverpod patterns cho Commerce state (shops, orders, products)
- Hive/Isar offline storage cho order pipeline
- Image caching strategy cho product catalog
- Barcode scanner integration cho inventory
- Bluetooth printer cho in đơn (Commerce-specific)
- VNPay / MoMo SDK mobile integration
- Push notification (FCM/APNs) cho order updates
1---2name: mobile-design3description: Design formula cho MOBILE APP (Flutter / React Native / SwiftUI / Jetpack Compose / iOS native / Android native). Auto-trigger khi chạm file .dart/.swift/.kt/.java mobile hoặc user nói build app mobile, màn hình mobile, screen, widget Flutter, RN component. KHÔNG dùng cho web — web có skill frontend-design riêng.4---56# Mobile Design Formula (MOBILE APP ONLY)78## AUTO-TRIGGER910Invoke **lần đầu tiên mỗi session** khi:11- User nói: "build app/màn hình/screen/widget Flutter/RN"12- User nói: "thêm/sửa UI mobile/app"13- Agent sắp edit/write file `.dart .swift .kt .java` (trong project mobile)14- Agent sắp chạm thư mục `mobile/` `lib/` `ios/` `android/`1516## KHÔNG dùng khi17- Web (React, Next.js, Vue, Svelte, HTML/CSS) → dùng `frontend-design`18- Backend — không có UI1920## Tư duy cốt lõi2122Mobile ≠ Web thu nhỏ. Công thức khác hoàn toàn:2324| | Web | Mobile |25|---|-----|--------|26| Typography scale | Dynamic clamp(44-72px) | Fixed scale (24/20/16/14/12sp) |27| Motion | Long (1.5-3s entrance) | Short (200-400ms) — instant feedback |28| Spacing | py-32 (128px) section | 16dp/24dp base unit |29| Touch target | N/A | Min 44pt iOS / 48dp Android |30| Navigation | Scroll/link | Tab bar / bottom nav / stack |31| Aesthetic | Can be experimental | Platform conventions (Material 3 / HIG) |32| Performance | Depends on device | **Critical** — 60fps mandatory |3334## Platform conventions (BẮT BUỘC tuân thủ)3536### Flutter37- Material 3 (Android) / Cupertino (iOS) — detect platform, render đúng widget38- Dùng `Theme.of(context)` thay hardcode color39- `MediaQuery` cho responsive, `SafeArea` cho notch40- `Hero` animation cho screen transition41- State: Riverpod / BLoC, KHÔNG setState cho state phức tạp4243### React Native44- `Platform.OS` check để render iOS/Android khác nhau45- `SafeAreaView` (react-native-safe-area-context)46- `react-native-reanimated` cho animation (60fps), KHÔNG Animated API cũ47- Navigation: React Navigation (stack/tab/drawer)4849### SwiftUI / Jetpack Compose50- Follow Apple HIG / Material 3 spec 100%51- System fonts, system colors (dark mode auto)52- Accessibility-first: VoiceOver / TalkBack5354## Design tokens (cho Commerce mobile app)5556```dart57// Flutter example — lib/core/theme.dart58class AppColors {59 // Light mode60 static const bgPrimary = Color(0xFFF5F5F7);61 static const bgCard = Color(0xFFFFFFFF);62 static const textPrimary = Color(0xFF1A1A1A);63 static const textMuted = Color(0xFF666666);64 static const accent = Color(0xFF007AFF); // iOS blue — hoặc Material 3 seed65 static const danger = Color(0xFFFF3B30);66 static const border = Color(0xFFE5E5E7);6768 // Dark mode69 static const bgPrimaryDark = Color(0xFF000000);70 static const bgCardDark = Color(0xFF1C1C1E);71 static const textPrimaryDark = Color(0xFFF5F0EB);72 // ...73}7475class AppSpacing {76 static const xs = 4.0; // 4dp77 static const sm = 8.0;78 static const md = 16.0; // base79 static const lg = 24.0;80 static const xl = 32.0;81 static const xxl = 48.0;82}8384class AppTypography {85 static const display = TextStyle(fontSize: 32, fontWeight: FontWeight.w700, height: 1.2);86 static const title = TextStyle(fontSize: 24, fontWeight: FontWeight.w600, height: 1.25);87 static const headline = TextStyle(fontSize: 20, fontWeight: FontWeight.w600);88 static const body = TextStyle(fontSize: 16, fontWeight: FontWeight.w400, height: 1.5);89 static const bodySmall = TextStyle(fontSize: 14, fontWeight: FontWeight.w400, height: 1.4);90 static const caption = TextStyle(fontSize: 12, fontWeight: FontWeight.w500, letterSpacing: 0.5);91}9293class AppRadius {94 static const sm = 8.0;95 static const md = 12.0;96 static const lg = 16.0; // card/modal default97 static const xl = 24.0;98 static const pill = 999.0;99}100```101102## Mobile UX rules1031041. **Touch target ≥ 44pt (iOS) / 48dp (Android)** — không được nhỏ hơn1052. **Feedback trong 100ms** — haptic, visual press state1063. **Loading ≤ 300ms → không cần indicator** (user không kịp nhận ra)1074. **Loading > 1s → phải có skeleton/shimmer** (không spinner thuần)1085. **Gesture natural** — swipe back iOS, pull-to-refresh, long-press menu1096. **Offline-first** — cache data local, sync background (quan trọng với Commerce VN)1107. **Keyboard awareness** — scroll content lên khi keyboard mở, don't hide inputs1118. **Error recovery** — mọi error phải có CTA retry, không dead-end112113## Anti-patterns114115| Sai | Đúng |116|-----|------|117| Fixed pixel height | `MediaQuery.of(context).size.height * x` |118| setState cho toàn screen | Riverpod selector / BLoC state slice |119| `print()` debug | `debugPrint()` hoặc logger package |120| Hardcode color | `Theme.of(context).colorScheme.xxx` |121| Blocking main thread | `compute()` cho heavy work |122| Image.network không cache | `cached_network_image` package |123| `setState(() {})` sau async gap không check `mounted` | `if (!mounted) return;` |124| Web design system (liquid glass, GSAP) | Platform conventions — Material/Cupertino |125126## Self-check trước khi ship mobile UI127128```129□ Touch targets ≥ 44pt/48dp?130□ Theme tokens dùng nhất quán (không hardcode color/spacing)?131□ Dark mode support?132□ Loading state (skeleton, không spinner thuần)?133□ Empty state có illustration + CTA?134□ Error state có retry button?135□ Keyboard handling (scroll, dismiss, action button)?136□ SafeArea cho notch/home indicator?137□ Accessibility (semanticsLabel, contrast ≥ 4.5:1)?138□ 60fps khi scroll list dài? (flutter profile mode test)139□ Offline graceful (cached data + sync indicator)?140□ Haptic feedback trên action quan trọng?141```142143## TODO — khi Commerce bắt đầu build mobile144145Hiện chưa có project mobile nào của anh active. Khi bắt đầu Flutter admin app, expand skill này với:146- Riverpod patterns cho Commerce state (shops, orders, products)147- Hive/Isar offline storage cho order pipeline148- Image caching strategy cho product catalog149- Barcode scanner integration cho inventory150- Bluetooth printer cho in đơn (Commerce-specific)151- VNPay / MoMo SDK mobile integration152- Push notification (FCM/APNs) cho order updates