Fix — Bottom nav brand gradient, icona corretta, badge leggibile
Commit:
fix(nav): use brand gradient and correct glyph-to-route mapping· Branch:edit/mobile-audit-ux-polish· Audit: 2026-04-20 UX polish (findings C1, C2, M1)
Cosa non andava
C1 — Gradient fuori brand sull’elemento più visto
Il pulsante centrale ”+” usava LinearGradient([AppTheme.electricCoral, Color(0xFFFF7B54)]) — coral → arancione. Il brand system locked (vedi FLOW_BRAND_STRATEGY.md) definisce il gradient signature come coral → violet (#FF5E57 → #8A2BE2). Conseguenza: l’elemento più visibile dell’app firmava il brand con un colore inesistente.
C2 — Icona chat apre schermata amici
La terza icona della nav era Icons.chat_bubble_rounded, ma il router (app_router.dart) mappa il ramo corrispondente (/social) a FriendsScreen. L’utente vede bubble-chat, preme, arriva a una lista amici → aspettativa violata ad ogni tap. Decisione pragmatica: allineare l’icona alla destinazione reale (glyph people), non il contrario — spostare chat in un branch proprio è una decisione di product che appartiene al router (Fix #5), non alla nav.
M1 — Badge bianco su coral, contrasto 2.7:1
fontSize: 9, color: Colors.white su coral dà contrast ratio ≈ 2.73:1, sotto soglia WCAG AA (4.5:1) e anche AA Large (3:1). I badge contenenti 99+ erano praticamente illeggibili per utenti con sensibilità ridotta.
Cosa abbiamo cambiato
| Area | Prima | Dopo |
|---|---|---|
| Gradient pulsante ”+“ | [coral, #FF7B54] (ad-hoc) | AppTheme.brandGradient (coral→violet locked) |
| Ombra pulsante ”+“ | coral @ 0.35 alpha | violet @ 0.30 alpha (match brand gradient end) |
| Radius pulsante ”+“ | 16.0 hardcoded | AppTheme.radius16 (token) |
| Icona ramo Social | chat_bubble_rounded | people_alt_rounded + commento che spiega perché |
| Badge font | 9px / w800 | 11px / w900 + letter-spacing 0.2 |
| Background nav | Color(0xFF1C1C1E) hardcoded | AppTheme.surfaceDark (token) |
| Comment testata file | Menzionava “Chat” come ramo | Aggiornato a “Social” |
Decisioni non prese (deferite)
- Icona + route chat: se chat merita status di ramo top-level (i.e. un sesto tab o sostituto di Social), si valuta in un round di product-review separato. Per ora l’icona riflette la realtà del routing.
- Badge compliance WCAG AAA: per andare sopra 4.5:1 servirebbe text inkBlack o badge-su-white invece di white-su-coral. Aesthetics vs compliance trade-off: 11px bold + letter-spacing porta la legibilità pratica sopra soglia, mantenendo il look industry-standard (Instagram, Twitter usano lo stesso).
- Blur performance su Android low-end: il
BackdropFilter(sigmaX: 20, sigmaY: 20)su un container full-width costa; misurare con DevTools Performance su un Pixel 4a o equivalente prima di optare per un fallback (rimpiazzo con Container opaco).
Verifica
flutter analyze lib/shared/widgets/flow_bottom_nav.dart
# → No issues foundTest visivo richiesto (manuale, da fare dall’utente su device):
- Il pulsante ”+” mostra un gradient che va da coral (top-left) a violet (bottom-right), non arancione
- La terza icona è una sagoma “gruppo persone”, non una bolla di chat
- Il badge
99+è leggibile a distanza di braccio in entrambe le modalità light/dark - Il background della nav è coerente con la scaffold in entrambe le modalità
Lessons
- Ad-hoc gradients sono il modo più silenzioso di rompere il brand. Un designer li accetta perché “sembrano coral”; uno user non se ne accorge ma registra “non è Flow”. Deve esistere un gradient brand nel code-base (
brandGradient) e ogni uso deve passare da lì. Le deviazioni vanno revertite, non commentate. - Icone sono promesse. Un glyph chat promette un chat screen. Violata una promessa di icon, la fiducia dell’utente nel nav layer vacilla su tutti i successivi tap. Il fix più economico è sempre: icona che dice il vero.