# Flutter Mobile Development Rules This document defines Flutter mobile development constraints. ## Design System ### Design Tokens All UI styling must use design tokens from `apps/lib/core/theme/design_tokens.dart`: | Type | Usage | |------|-------| | Colors | `AppColors.primary`, `AppColors.slate500`, `AppColors.background` | | Spacing | `AppSpacing.xs`, `AppSpacing.sm`, `AppSpacing.md` | | Radius | `AppRadius.sm`, `AppRadius.md`, `AppRadius.lg` | **NEVER hardcode colors, sizes, or spacing values.** ### Reuse Existing Components Use pre-built components instead of creating custom ones: - Buttons: Use `AppButton` widget from `apps/lib/shared/widgets/app_button.dart` - Input fields: Use standard Flutter `TextField` with `InputDecoration` - Loading states: Use built-in loading indicators ## New Page Design Workflow 1. **Analyze existing pages**: Study login, register, home screens for: - Layout structure (centered form, padding, spacing) - Typography hierarchy (title 28px bold, label 13px, hint 14px) - Component usage (AppButton, TextField style) - Color and spacing tokens 2. **Use frontend-design skill for mockups**: ``` Use the `frontend-design` skill to create HTML/CSS mockups for review Match colors to `apps/lib/core/theme/design_tokens.dart` Match spacing to `AppSpacing` values Match radius to `AppRadius` values ``` 3. **Verify design tokens**: - All colors from `AppColors` - All spacing from `AppSpacing` - All radius from `AppRadius` - NO hardcoded values 4. **Code review checklist**: - [ ] All colors/spacing/radius use design tokens - [ ] Reuses existing components (AppButton) - [ ] Consistent with existing page patterns - [ ] No magic numbers ## Layout Mapping Rules Map design layout properties to Flutter explicitly: 1. **Always set `crossAxisAlignment` on `Row`/`Column`**: - `alignItems: center` -> `CrossAxisAlignment.center` - `alignItems: start` -> `CrossAxisAlignment.start` - `alignItems: stretch` -> `CrossAxisAlignment.stretch` 2. **Map full container chain**: From root to leaf, ensure each `alignItems` and `justifyContent` has a Flutter equivalent. 3. **Analyze before coding**: Verify each container's alignment settings. ## Centering and Visual Balance 1. Centering must be evaluated inside **`SafeArea`** bounds, not full-screen bounds. 2. Avoid relying on proportional `Spacer` values as the only centering mechanism for critical content. 3. For layouts with persistent top/bottom regions (e.g., headers or footers), center the primary content in the remaining available region. 4. Distinguish geometric centering from visual centering; validate final visual balance with screenshot review. ## Quality Gate For important screens, add widget tests that reduce layout-regression risk: 1. Verify primary content remains centered relative to the usable viewport. 2. Add at least one constrained viewport scenario (small height or large text scale). ## Prohibitions - DO NOT use colors not defined in design tokens - DO NOT skip design container layers - DO NOT start implementation before retrieving design variables - DO NOT hardcode colors; use design variables ## UI Feedback System **MUST use the Toast system for all user feedback messages.** ### Components | Component | Use Case | Example | |-----------|----------|---------| | `Toast.show()` | Global temporary notifications | Success/error feedback after action | | `AppBanner` | Inline form validation errors | Login form error message | ### Toast Types ```dart enum ToastType { info, success, warning, error } ``` ### Usage Examples **Global Toast (auto-dismiss):** ```dart Toast.show(context, '保存成功', type: ToastType.success); Toast.show(context, '网络错误', type: ToastType.error); Toast.show(context, '正在加载...', type: ToastType.info, duration: Duration(seconds: 3)); ``` **Inline Banner (persistent):** ```dart AppBanner(message: '邮箱或密码错误', type: ToastType.error) AppBanner(message: '请检查输入', type: ToastType.warning) ``` ### Rules - Use `Toast` for transient feedback that auto-dismisses - Use `AppBanner` for persistent inline messages (form errors) - DO NOT create custom SnackBar, Dialog, or Banner components - DO NOT use raw `ScaffoldMessenger`