veza/apps/web/dev_audit/frontend/09_scalability_ui.md
senke 5f88c56113 fix: UI remediation Phase 1 (S0-S5) + Phase 2 Sprint 6 shadow system
Phase 1:
- S0: Fix open redirect (safeNavigate), delete AuthContext/legacy auth, encrypt API keys, gitignore .env files
- S1: Split client.ts god object into 5 modules, unify toast system, delete unused Sidebar
- S2: Add glass button variant, migrate 32 z-index to SUMI tokens, fix card dark mode
- S3: Skip nav link, aria-hidden on icons, focus-visible ring fixes, alt attrs, aria-live regions
- S4: React.memo on list items, fix key={index}, loading=lazy on images
- S5: Branded loading screen, page transitions respect reduced-motion, LikeButton micro-interaction, i18n sidebar/header

Phase 2 Sprint 6:
- Wire Tailwind shadow utilities to SUMI tokens in @theme block (fixes 50+ files)
- Define shadow-card/shadow-card-hover tokens
- Remove dark:shadow-none workarounds from card.tsx (SUMI handles per-theme shadows)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 10:13:44 +01:00

6.6 KiB

Phase I — Scalabilité UI


I1. Ajout de 50 écrans

Routing — ⚠️ Partiel

  • L'architecture de routing routeConfig.tsx est centralisée avec des fonctions getPublicRoutes(), getProtectedRoutes(), etc. [routeConfig.tsx:57-109]. Ajouter une route est simple (une ligne), mais toutes les routes sont dans un seul fichier.
  • Pour 50 écrans supplémentaires, ce fichier deviendrait un bottleneck. Recommandation : migrer vers un routing file-based ou colocalisé par feature.
  • Le lazy loading via createLazyComponent [lazy-component/createLazyComponent.tsx] est scalable — chaque nouvelle page est automatiquement code-splittée.

Design system — Prêt

  • Le design system SUMI v2.0 couvre les primitives nécessaires : Button (7 variants), Input, Select, Dialog, Tabs, Card, Badge, Table, DropdownMenu, DatePicker, etc. [02_design_system_inventory.md]
  • Les tokens (couleurs, typo, spacing, shadows) sont suffisamment riches pour supporter de nouveaux écrans sans modification.

Convention de nommage — Prêt

  • Pattern feature-based clair : features/{name}/pages/, features/{name}/components/, features/{name}/hooks/
  • Convention PascalCase pour les composants, camelCase pour les hooks
  • Pattern XxxSkeleton.tsx, XxxEmpty.tsx, useXxx.ts, types.ts, index.ts bien établi

State management — Prêt

  • Zustand pour l'état global (UI, auth, cart) est scalable — chaque feature peut avoir son store
  • React Query pour le server state est naturellement scalable — chaque query est indépendante
  • La combinaison des deux évite un store central monolithique

Verdict : ⚠️ Partiel — Le design system et le state management sont prêts, mais le routing centralisé et la migration incomplète components/views/features/pages/ freinent.


I2. Theming / Dark mode

Tokenisation — Prêt

  • 100% des couleurs sont tokenisées dans index.css via CSS variables SUMI [index.css:15-296]
  • 0 couleur hardcodée (bg-[#...]) dans les className
  • Palette complète dark + light définie [index.css:301-364]

Migration effort — Minimal

  • 24 fichiers utilisent le préfixe dark: de Tailwind — ce qui est très peu car le theming est géré par data-theme attribute + CSS variables, pas par le mécanisme dark: de Tailwind.
  • Le switch de thème est fonctionnel via uiStore.setTheme() [stores/ui.ts:35-51] et ThemeProvider [components/theme/ThemeProvider.tsx]

Valeurs hardcodées à migrer

  • #ffffff dans index.css:363 (primary-foreground light) — acceptable dans le fichier de tokens
  • #8b7ec8 pour chart-5 [index.css:240] — dans les tokens
  • Couleurs contextuelles (graffiti-magenta, gaming-gold, terminal-green, sakura) [index.css:202-205] — dans les tokens

Verdict : Prêt — Le theming est pleinement fonctionnel avec un effort minimal pour ajouter des thèmes supplémentaires.


I3. Internationalisation (i18n)

Système en place

  • i18next + react-i18next + i18next-browser-languagedetector installés [package.json]
  • Configuration dans lib/i18n.ts
  • 2 langues : en.json et fr.json dans src/locales/
  • Hook useTranslation.ts custom disponible [hooks/useTranslation.ts]

Adoption

  • ~80+ fichiers utilisent useTranslation ou t() — adoption significative
  • ~35+ fichiers contiennent des strings hardcodées en anglais dans le JSX :
    • "No Cover", "No lyrics available", "No courses found", "No messages yet", "No equipment found", "Loading...", "Error" [voir 08_technical_debt_frontend.md]
    • Ces strings devraient utiliser t() pour être traduisibles

RTL support

  • Aucun support RTL détecté. Pas de dir attribute, pas de classes rtl:.
  • Pour l'arabe, l'hébreu, etc., une refonte du layout serait nécessaire.

Formatage dates/nombres

  • date-fns (4.1.x) installé — supporte la localisation
  • La localisation de date-fns est-elle configurée avec i18next ? [DONNÉES INSUFFISANTES]

Verdict : ⚠️ Partiel — Le système i18n est en place et partiellement adopté, mais ~35+ fichiers ont des strings hardcodées et le RTL n'est pas supporté.


I4. White-labeling / Multi-tenant UI

Logo et branding

  • Le logo/branding semble hardcodé dans les composants (à vérifier dans Header/Sidebar)
  • Les couleurs sont tokenisées → changement de palette possible
  • Les polices sont en variables CSS → personnalisables

Couleurs externalisables

  • Via les CSS variables SUMI — un tenant pourrait surcharger les variables :root
  • Les couleurs contextuelles (graffiti-magenta, gaming-gold, etc.) montrent une flexibilité de palette

Layouts personnalisables

  • Les layouts (Sidebar, Header, DashboardLayout) sont codés en dur
  • Pas de configuration de layout par tenant

Verdict : Bloqué — Le white-labeling nécessiterait un refactoring significatif pour externaliser le branding, bien que les tokens CSS offrent une base.


I5. Performance à l'échelle

Virtualisation des listes

  • @tanstack/react-virtual installé et utilisé [package.json, components/ui/virtualized-list/VirtualizedList.tsx]
  • VirtualizedList.tsx (125L) — composant générique de virtualisation
  • Chat messages virtualisés [features/chat/components/virtualized-chat-messages/]

Pagination

  • Pagination serveur implémentée dans les services API :
    • playlistService.ts : page, limit, safeLimit, safePage [playlistService.ts]
    • trackService.ts : page, limit en query params [trackService.ts]
    • socialService.ts : page = 1 [socialService.ts]
    • marketplaceService.ts : page/limit [marketplaceService.ts]
  • Composants de pagination UI : TrackListPaginationNav.tsx (148L), TrackListPaginationInfo.tsx (25L)

Infinite scroll

  • features/tracks/hooks/useInfiniteScroll.ts — hook dédié
  • components/ui/virtualized-list/useInfiniteScroll.ts — hook pour la liste virtualisée

Cursor-based pagination

  • Pas de pagination cursor-based détectée — uniquement offset/limit

Verdict : Prêt — Virtualisation, pagination serveur et infinite scroll sont en place.


Tableau récapitulatif

Dimension Verdict Détail
Ajout de 50 écrans ⚠️ Partiel DS prêt, routing centralisé à améliorer
Theming / Dark mode Prêt 100% tokenisé, dark/light fonctionnel
i18n ⚠️ Partiel Système en place, adoption ~70%, pas de RTL
White-labeling Bloqué Branding hardcodé, pas de config par tenant
Performance à l'échelle Prêt Virtualisation, pagination, infinite scroll