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

AreaPrimaDopo
Gradient pulsante ”+“[coral, #FF7B54] (ad-hoc)AppTheme.brandGradient (coral→violet locked)
Ombra pulsante ”+“coral @ 0.35 alphaviolet @ 0.30 alpha (match brand gradient end)
Radius pulsante ”+“16.0 hardcodedAppTheme.radius16 (token)
Icona ramo Socialchat_bubble_roundedpeople_alt_rounded + commento che spiega perché
Badge font9px / w80011px / w900 + letter-spacing 0.2
Background navColor(0xFF1C1C1E) hardcodedAppTheme.surfaceDark (token)
Comment testata fileMenzionava “Chat” come ramoAggiornato 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 found

Test 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.