|
| 1 | +# Module 00: UI/UX Should Include / Should NOT Include |
| 2 | + |
| 3 | +## Purpose |
| 4 | +This module provides an explicit consolidated checklist of UI/UX patterns that **SHOULD** and **SHOULD NOT** be included in the Pasahe app. Use this as a quick reference during development and code review. |
| 5 | + |
| 6 | +**Related:** [01-localization-issues](./01-localization-issues.md) | [02-typography-issues](./02-typography-issues.md) | [03-color-contrast-issues](./03-color-contrast-issues.md) | [11-navigation-error-feedback-patterns](./11-navigation-error-feedback-patterns.md) |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## SHOULD NOT Include ❌ |
| 11 | + |
| 12 | +### Typography & Text |
| 13 | + |
| 14 | +| Pattern | Finding ID | Evidence | Why Avoid | |
| 15 | +|---------|------------|----------|-----------| |
| 16 | +| Hardcoded font sizes < 11sp | Typo-01, Typo-02 | `passenger_bottom_sheet.dart:127` - `fontSize: 12` in subtitle (borderline) | WCAG 1.4.4 failure; system text scale breaks layout | |
| 17 | +| Fixed text scaling without safeguards | Typo-09 | `splash_screen.dart:55-70` - Animation text lacks TextScaler awareness | Users with vision impairment cannot read content | |
| 18 | +| Non-semantic text styling | Typo-03, Typo-04 | Multiple screens using `TextStyle(fontSize: X)` directly | Inconsistent with Material 3 design system | |
| 19 | + |
| 20 | +### Color & Theming |
| 21 | + |
| 22 | +| Pattern | Finding ID | Evidence | Why Avoid | |
| 23 | +|---------|------------|----------|-----------| |
| 24 | +| Raw `Colors.black` / `Colors.white` | Color-01, Color-02 | `error_message_banner.dart:21` - `color: colorScheme.error` ✅ (good) vs hardcoded found elsewhere | Breaks dark mode; non-themeable | |
| 25 | +| Alpha values without semantic meaning | Color-08 | Various `withOpacity()` calls | Fragile; use `colorScheme` containers instead | |
| 26 | +| Missing error container colors | Color-03 | Some widgets use `backgroundColor: Colors.red` | Should use `colorScheme.errorContainer` | |
| 27 | + |
| 28 | +### Localization |
| 29 | + |
| 30 | +| Pattern | Finding ID | Evidence | Why Avoid | |
| 31 | +|---------|------------|----------|-----------| |
| 32 | +| Hardcoded user-facing strings | L10n-01 through L10n-12 | `offline_status_banner.dart:50-52` - Hardcoded English strings | App targets Tagalog/English bilingual users | |
| 33 | +| Non-internationalized error messages | L10n-02 | `main_screen.dart:296-301` - `'Failed to get location'` | Error messages must be localized | |
| 34 | +| Date/number formatting without locale | L10n-11 | Currency displays may lack proper PHP formatting | Financial data requires cultural formatting | |
| 35 | + |
| 36 | +### Accessibility |
| 37 | + |
| 38 | +| Pattern | Finding ID | Evidence | Why Avoid | |
| 39 | +|---------|------------|----------|-----------| |
| 40 | +| Interactive elements without semantics | A11y-03 | Map picker buttons may lack `tooltip` or `semanticsLabel` | Screen reader users cannot identify controls | |
| 41 | +| Color-only status indicators | A11y-02 | Status banners rely solely on color | Colorblind users cannot distinguish states | |
| 42 | +| Missing loading state announcements | A11y-05 | `_isLoadingAddress` transitions lack semantics | Screen reader users don't know loading started | |
| 43 | + |
| 44 | +### Navigation & Feedback |
| 45 | + |
| 46 | +| Pattern | Finding ID | Evidence | Why Avoid | |
| 47 | +|---------|------------|----------|-----------| |
| 48 | +| Silent failures (no user feedback) | Nav-01 | `map_picker_screen.dart:178-209` - Address loading errors may be silent | Users don't know something failed | |
| 49 | +| No retry mechanism for recoverable errors | Nav-03 | `region_download_screen.dart:360` - Retry exists but not consistently applied | Users stuck on error states | |
| 50 | +| Missing back gesture handling | Nav-05 | Bottom sheets may not handle back properly on Android | Unexpected dismissal behavior | |
| 51 | +| Generic error messages | Nav-02 | `main_screen.dart:344-347` - Generic `'Failed to get address'` | Doesn't help user resolve issue | |
| 52 | + |
| 53 | +### Network & Offline |
| 54 | + |
| 55 | +| Pattern | Finding ID | Evidence | Why Avoid | |
| 56 | +|---------|------------|----------|-----------| |
| 57 | +| No offline indication | Offline-01 | Screens without `OfflineStatusBanner` | Users don't know why features fail | |
| 58 | +| Rate limit without UX feedback | Map-01 | `geocoding_service.dart:47-60` - Throttle exists but no UI | Users spam search, get no results, confused | |
| 59 | +| Blocking loading without progress | Offline-03 | `region_download_screen.dart:329-330` - Binary loading state | Large downloads (>500MB) need progress | |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +## SHOULD Include ✅ |
| 64 | + |
| 65 | +### Typography & Text |
| 66 | + |
| 67 | +| Pattern | Finding ID | Evidence | Implementation | |
| 68 | +|---------|------------|----------|----------------| |
| 69 | +| Theme-derived text styles | Typo-S1 | `passenger_bottom_sheet.dart:45` - `textTheme.titleLarge` | Use `Theme.of(context).textTheme` exclusively | |
| 70 | +| TextScaler-aware layouts | Typo-S2 | `passenger_bottom_sheet.dart:20-30` - `MediaQuery.viewInsets` usage | Wrap in `LayoutBuilder` or overflow handlers | |
| 71 | +| Semantic font weights | Typo-S3 | `passenger_bottom_sheet.dart:127` - `FontWeight.w600` | Use `FontWeight` constants, not raw numbers | |
| 72 | +| Proper text contrast | Color-S1 | `error_message_banner.dart:27` - `colorScheme.onErrorContainer` | Always use on-* colors for text on containers | |
| 73 | + |
| 74 | +**Evidence - Good Pattern (Theme-derived styling):** |
| 75 | +```dart |
| 76 | +// File: lib/src/presentation/widgets/main_screen/passenger_bottom_sheet.dart:44-48 |
| 77 | +textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold), |
| 78 | +``` |
| 79 | + |
| 80 | +### Color & Theming |
| 81 | + |
| 82 | +| Pattern | Finding ID | Evidence | Implementation | |
| 83 | +|---------|------------|----------|----------------| |
| 84 | +| ColorScheme usage | Color-S2 | `passenger_bottom_sheet.dart:44` - `colorScheme.outlineVariant` | Use `Theme.of(context).colorScheme` | |
| 85 | +| Container colors with proper contrast | Color-S3 | `passenger_bottom_sheet.dart:83-88` - `primaryContainer.withValues(alpha: 0.3)` | Alpha values only on container colors | |
| 86 | +| Theme-aware error states | Color-S4 | `error_message_banner.dart:16` - `colorScheme.errorContainer` | Use semantic error containers | |
| 87 | + |
| 88 | +**Evidence - Good Pattern (Semantic Error Container):** |
| 89 | +```dart |
| 90 | +// File: lib/src/presentation/widgets/main_screen/error_message_banner.dart:16-20 |
| 91 | +decoration: BoxDecoration( |
| 92 | + color: colorScheme.errorContainer, |
| 93 | + borderRadius: BorderRadius.circular(12), |
| 94 | +), |
| 95 | +``` |
| 96 | + |
| 97 | +### Localization |
| 98 | + |
| 99 | +| Pattern | Finding ID | Evidence | Implementation | |
| 100 | +|---------|------------|----------|----------------| |
| 101 | +| AppLocalizations for all strings | L10n-S1 | `main_screen.dart:367` - `AppLocalizations.of(context)!.routeSavedMessage` | Every user-facing string via `.arb` files | |
| 102 | +| Locale-aware formatting | L10n-S2 | Currency formatting with proper locale | Use `NumberFormat` with locale | |
| 103 | +| RTL layout support | L10n-S3 | Widgets using `EdgeInsetsDirectional` | Avoid absolute left/right where possible | |
| 104 | + |
| 105 | +### Accessibility |
| 106 | + |
| 107 | +| Pattern | Finding ID | Evidence | Implementation | |
| 108 | +|---------|------------|----------|----------------| |
| 109 | +| Semantic labels on icons | A11y-S1 | Icon buttons with `tooltip` parameter | Always provide `tooltip` for icon buttons | |
| 110 | +| Loading state announcements | A11y-S2 | `AnimatedSwitcher` for state changes | Wrap in `Semantics` with proper labels | |
| 111 | +| Proper touch targets | A11y-S3 | `passenger_bottom_sheet.dart:147-150` - `minWidth: 40, minHeight: 40` | Minimum 48dp touch targets | |
| 112 | + |
| 113 | +**Evidence - Good Pattern (Accessible Touch Targets):** |
| 114 | +```dart |
| 115 | +// File: lib/src/presentation/widgets/main_screen/passenger_bottom_sheet.dart:147-150 |
| 116 | +IconButton( |
| 117 | + icon: Icon(Icons.remove, /* ... */), |
| 118 | + onPressed: onDecrement, |
| 119 | + constraints: const BoxConstraints(minWidth: 40, minHeight: 40), |
| 120 | +) |
| 121 | +``` |
| 122 | + |
| 123 | +### Navigation & Feedback |
| 124 | + |
| 125 | +| Pattern | Finding ID | Evidence | Implementation | |
| 126 | +|---------|------------|----------|----------------| |
| 127 | +| Modal bottom sheets with handles | Nav-S1 | `passenger_bottom_sheet.dart:50-57` - Drag handle | Include visual handle for discoverability | |
| 128 | +| SnackBar for transient messages | Nav-S2 | `main_screen.dart:367-374` - Route saved confirmation | Use `SnackBarBehavior.floating` with shape | |
| 129 | +| Dialog for destructive actions | Nav-S3 | `region_download_screen.dart:139-151` - Delete confirmation | Confirm irreversible actions | |
| 130 | +| Smooth loading transitions | Nav-S4 | `map_picker_screen.dart:792-808` - `AnimatedSwitcher` | Transition between loading/content/error | |
| 131 | +| Retry buttons for errors | Nav-S5 | `region_download_screen.dart:360` - Retry button | Allow user-initiated recovery | |
| 132 | + |
| 133 | +**Evidence - Good Pattern (Modal with Handle):** |
| 134 | +```dart |
| 135 | +// File: lib/src/presentation/widgets/main_screen/passenger_bottom_sheet.dart:50-57 |
| 136 | +Center( |
| 137 | + child: Container( |
| 138 | + width: 40, |
| 139 | + height: 4, |
| 140 | + decoration: BoxDecoration( |
| 141 | + color: colorScheme.outlineVariant, |
| 142 | + borderRadius: BorderRadius.circular(2), |
| 143 | + ), |
| 144 | + ), |
| 145 | +), |
| 146 | +``` |
| 147 | + |
| 148 | +**Evidence - Good Pattern (Floating SnackBar):** |
| 149 | +```dart |
| 150 | +// File: lib/src/presentation/screens/main_screen.dart:367-374 |
| 151 | +ScaffoldMessenger.of(context).showSnackBar( |
| 152 | + SnackBar( |
| 153 | + content: Text(AppLocalizations.of(context)!.routeSavedMessage), |
| 154 | + behavior: SnackBarBehavior.floating, |
| 155 | + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), |
| 156 | + ), |
| 157 | +); |
| 158 | +``` |
| 159 | + |
| 160 | +### Network & Offline |
| 161 | + |
| 162 | +| Pattern | Finding ID | Evidence | Implementation | |
| 163 | +|---------|------------|----------|----------------| |
| 164 | +| Offline status banners | Offline-S1 | `offline_status_banner.dart:22-76` - Connectivity-aware banner | Show on all screens with network dependency | |
| 165 | +| Rate limit feedback | Map-S1 | `geocoding_service.dart:47-60` - Throttle with debounce | Combine with UI messaging | |
| 166 | +| Progressive loading states | Offline-S2 | `map_picker_screen.dart:46-47` - `ValueNotifier<bool>` for states | Multiple loading states (search vs address) | |
| 167 | +| Cached data fallbacks | Offline-S3 | `offline_mode_service.dart` - Offline-first patterns | Graceful degradation with cache | |
| 168 | + |
| 169 | +**Evidence - Good Pattern (Offline Status Banner):** |
| 170 | +```dart |
| 171 | +// File: lib/src/presentation/widgets/main_screen/offline_status_banner.dart:22-76 |
| 172 | +class OfflineStatusBanner extends StatelessWidget { |
| 173 | + final ConnectivityStatus status; |
| 174 | + // ... displays contextual message based on connectivity state |
| 175 | + // with "Go Online" button for manual offline mode |
| 176 | +} |
| 177 | +``` |
| 178 | + |
| 179 | +### Animation & Motion |
| 180 | + |
| 181 | +| Pattern | Finding ID | Evidence | Implementation | |
| 182 | +|---------|------------|----------|----------------| |
| 183 | +| Smooth splash animations | Anim-S1 | `splash_screen.dart:55-70` - Staggered animations | Use `AnimationController` with curves | |
| 184 | +| Map pin animations | Anim-S2 | `map_picker_screen.dart:62-73` - Pin bounce animation | Physical motion with `Curves.bounceOut` | |
| 185 | +| Loading shimmer/skeleton | Anim-S3 | To be implemented | Placeholder UI during content load | |
| 186 | + |
| 187 | +**Evidence - Good Pattern (Pin Animation):** |
| 188 | +```dart |
| 189 | +// File: lib/src/presentation/screens/map_picker_screen.dart:62-73 |
| 190 | +_pinBounceAnimation = Tween<double>(begin: 0, end: -20).animate( |
| 191 | + CurvedAnimation( |
| 192 | + parent: _pinAnimationController, |
| 193 | + curve: Curves.easeOut, |
| 194 | + reverseCurve: Curves.bounceOut, |
| 195 | + ), |
| 196 | +); |
| 197 | +``` |
| 198 | + |
| 199 | +--- |
| 200 | + |
| 201 | +## Quick Reference Checklist |
| 202 | + |
| 203 | +### Before Submitting PR |
| 204 | + |
| 205 | +- [ ] No hardcoded strings in new code (use `AppLocalizations`) |
| 206 | +- [ ] No raw `Colors.xxx` (use `colorScheme`) |
| 207 | +- [ ] No fixed font sizes without TextScaler handling |
| 208 | +- [ ] Touch targets minimum 48dp |
| 209 | +- [ ] Icon buttons have tooltips |
| 210 | +- [ ] Loading states visible to user |
| 211 | +- [ ] Error states have actionable messages |
| 212 | +- [ ] Offline status considered |
| 213 | +- [ ] Dialogs used for destructive actions |
| 214 | +- [ ] SnackBars used for confirmations |
| 215 | + |
| 216 | +### Code Review Focus Areas |
| 217 | + |
| 218 | +| Area | Check For | |
| 219 | +|------|-----------| |
| 220 | +| Typography | Theme-based, scalable, semantic weights | |
| 221 | +| Color | ColorScheme, proper contrast, no hardcoded values | |
| 222 | +| Localization | All strings externalized, RTL-safe layouts | |
| 223 | +| Accessibility | Touch targets, semantics, color-independent indicators | |
| 224 | +| Navigation | Proper back handling, clear transitions, state preservation | |
| 225 | +| Feedback | Loading states, error messages, retry options | |
| 226 | +| Offline | Status visibility, graceful degradation, cache usage | |
| 227 | + |
| 228 | +--- |
| 229 | + |
| 230 | +## Related Findings |
| 231 | + |
| 232 | +| Module | Relevant Findings | |
| 233 | +|--------|-------------------| |
| 234 | +| 01-localization-issues | L10n-01 through L10n-12 | |
| 235 | +| 02-typography-issues | Typo-01, Typo-02, Typo-03, Typo-09 | |
| 236 | +| 03-color-contrast-issues | Color-01, Color-02, Color-03, Color-08 | |
| 237 | +| 04-accessibility-strengths | A11y-S1 through A11y-S3 | |
| 238 | +| 06-map-offline-edge-cases | Map-01, Map-03, Map-04, Offline-01 | |
| 239 | +| 11-navigation-error-feedback-patterns | Nav-01 through Nav-S5 | |
| 240 | + |
| 241 | +--- |
| 242 | + |
| 243 | +## Version History |
| 244 | + |
| 245 | +| Version | Date | Changes | |
| 246 | +|---------|------|---------| |
| 247 | +| 1.0.0 | 2026-03-17 | Initial should/should not checklist | |
0 commit comments