# Nouvelle architecture UI & plan de refonte — Xpeditis **Date :** 2026-08-12 · **Branche :** `ui_update` **Prérequis de lecture :** [`design-system-audit.md`](./design-system-audit.md) (charte verrouillée) · [`ui-audit.md`](./ui-audit.md) (cartographie) > **Contrainte cardinale.** Toute valeur visuelle produite ici provient du §1–§22 de `design-system-audit.md`. > Aucune couleur, police, rayon ou token n'est introduit. Ce document ne fait que **réorganiser** et **appliquer** l'existant. --- ## Sommaire - [1. Principes directeurs](#1-principes-directeurs) - [2. Vocabulaire visuel appliqué](#2-vocabulaire-visuel-appliqué) - [3. App shell](#3-app-shell) - [4. Composants de navigation](#4-composants-de-navigation) - [5. Composants de contenu](#5-composants-de-contenu) - [6. Composants de saisie](#6-composants-de-saisie) - [7. Composants de surface](#7-composants-de-surface) - [8. Composants d'état](#8-composants-détat) - [9. Architecture de fichiers](#9-architecture-de-fichiers) - [10. Responsive](#10-responsive) - [11. Micro-interactions](#11-micro-interactions) - [12. Accessibilité](#12-accessibilité) - [13. Plan de refonte par lots](#13-plan-de-refonte-par-lots) - [14. Protocole de validation](#14-protocole-de-validation) - [15. Ce que je ne ferai pas](#15-ce-que-je-ne-ferai-pas) --- ## 1. Principes directeurs Quatre règles arbitrent chaque décision de la refonte. Elles sont volontairement peu nombreuses et opposables. **P1 — Le navy porte la structure, le turquoise porte l'action.** `brand-navy #10183A` = chrome, titres, surfaces d'autorité, état actif. `brand-turquoise #34CCCD` = action primaire, focus, sélection, accent de données. Cette règle remplace, à elle seule, les 816 usages de bleu générique. Elle n'invente rien : c'est la lecture littérale de la charte. **P2 — La densité est une fonctionnalité.** Xpeditis est un outil de transitaire : listes longues, colonnes nombreuses, comparaison de taux. La refonte va vers **plus d'information par écran**, pas moins. Concrètement : cartes KPI alignées à gauche et non centrées, tables en densité compacte par défaut, padding `p-4`/`p-5` plutôt que `p-6`, suppression des conteneurs décoratifs intermédiaires. **P3 — Une seule manière de faire chaque chose.** Un bouton, un champ, une table, une modale, un état vide. Les trois systèmes de boutons deviennent un. Les 7 paginations deviennent une. Toute variante doit être justifiée par un besoin fonctionnel distinct, pas par une préférence locale. **P4 — Le mouvement sert la compréhension.** Une animation n'est acceptée que si elle explique une transition d'état ou une relation spatiale. 120–200 ms, `ease-out`, sur `opacity` / `transform` uniquement. Tout le reste est supprimé. --- ## 2. Vocabulaire visuel appliqué ### 2.1 Rôles de couleur — dérivés stricts de la charte | Rôle | Token | Valeur | Application | |------|-------|--------|-------------| | Surface application | `bg-white` | `#FFFFFF` | Cartes, panneaux, tables | | Surface page | `neutral-50` | `#F8F9FC` | Fond de zone de contenu | | Surface d'autorité | `brand-navy` | `#10183A` | Sidebar admin, sections navy, en-têtes sombres | | Bordure | `--border` | `#E2E8F0` | Bordures 1px, séparateurs | | Texte principal | `brand-navy` | `#10183A` | Titres, valeurs KPI | | Texte courant | `neutral-800` | `#1E2859` | Corps | | Texte secondaire | `neutral-500` | `#5A6BB8` | Descriptions, métadonnées | | Action primaire | `brand-turquoise` | `#34CCCD` | CTA, boutons primaires | | Focus | `brand-turquoise` | `#34CCCD` | Anneau de focus (via `--ring`) | | État actif (nav) | `brand-navy` + fond `neutral-100` | `#10183A` / `#EDEEF5` | Item de sidebar actif | | Succès | `success` / `brand-green` | `#067224` | Accepté, validé, payé | | Erreur | `--destructive` | `#EF4444` | Refusé, erreur, suppression | | Avertissement | `amber-500` | `#F59E0B` | En attente, expiration proche | > **Trois substitutions systématiques, et rien d'autre :** > `blue-*` → `brand-turquoise` (action) ou `brand-navy` (structure) selon le rôle > `gray-*` → `neutral-*` (échelle déjà définie dans la charte) > `purple-*` / `emerald-*` / `orange-*` / `indigo-*` → rôle sémantique ci-dessus ### 2.2 Élévation — 3 niveaux, pas 6 L'audit relève 6 niveaux d'ombre utilisés sans règle. La refonte en retient trois : | Niveau | Classe | Usage | |--------|--------|-------| | 0 | `border` seul | Cartes, panneaux, tables — **défaut** | | 1 | `shadow-sm` | Éléments flottants ancrés : dropdowns, popovers, sidebar mobile | | 2 | `shadow-lg` | Éléments détachés : modales, drawers, toasts | `shadow-md`, `shadow-xl`, `shadow-2xl` et la classe fantôme `shadow-brand` sont retirés du produit. **La carte par défaut passe de `shadow-sm` à `border` seul** — c'est le principal levier pour un rendu net et non « cartonné ». ### 2.3 Rayons — 3 valeurs | Classe | Valeur | Usage | |--------|--------|-------| | `rounded-md` | 6px | Contrôles : boutons, champs, selects, badges carrés | | `rounded-lg` | 8px | Conteneurs : cartes, panneaux, modales, dropdowns | | `rounded-full` | — | Pilules, avatars, points d'état | `rounded-xl`, `rounded-2xl`, `rounded-3xl` sont retirés du produit. (Conservés uniquement sur la landing, traitée en dernier lot — voir §13, L9.) ### 2.4 Typographie appliquée L'échelle `text-h1…h6` / `text-body-*` / `text-label-*` de la charte est **enfin utilisée**, en remplacement de l'échelle Tailwind par défaut : | Élément | Token de charte | |---------|-----------------| | Titre de page | `text-h3` (24px/600, Manrope) | | Description de page | `text-body-sm` + `neutral-500` | | Titre de section / carte | `text-h5` (18px/500) | | Valeur KPI | `text-h2` (32px/600) + `brand-navy` | | Corps | `text-body-sm` (14px) — densité produit | | En-tête de table | `text-label` (12px/600, +0.05em, capitales) | | Cellule de table | `text-body-sm` | | Libellé de champ | `text-label-lg` (14px/600) | | Aide / erreur de champ | `text-body-xs` (12px) | > Le titre de page passe de `text-3xl` (30px) à `text-h3` (24px). C'est volontaire : combiné à la suppression du double titre (§3), l'écran gagne en hiérarchie **et** en espace utile. ### 2.5 Rythme d'espacement — échelle 4/8 Multiples retenus : **4, 8, 12, 16, 24, 32, 48**. (`gap-1` `gap-2` `gap-3` `gap-4` `gap-6` `gap-8` `gap-12`) | Contexte | Valeur | |----------|--------| | Padding de carte | `p-5` (20px) desktop, `p-4` mobile | | Padding de cellule de table | `px-4 py-3` (compact) / `px-4 py-4` (confortable) | | Gap de grille | `gap-4` | | Espacement entre sections | `space-y-6` | | Padding de zone de contenu | `p-4 lg:p-6 2xl:p-8` | --- ## 3. App shell ### 3.1 Structure cible ``` ┌──────────────────────────────────────────────────────────────┐ │ Sidebar (w-60 / w-16 replié) │ Topbar (h-14) │ │ ───────────────────────────── ├──────────────────────────────│ │ Logo [«] │ Breadcrumb ⌘K 🔔 🌐 👤 │ │ ├──────────────────────────────│ │ ── Pilotage │ │ │ ▸ Tableau de bord │ PageHeader │ │ ▸ Réservations │ Titre (h3) + description │ │ ▸ Documents │ [onglets] [actions] │ │ ▸ Suivi │ ────────────────────────── │ │ │ │ │ ── Ressources │ Contenu │ │ ▸ Wiki │ │ │ │ │ │ ── Organisation │ │ │ ▸ Paramètres │ │ │ · Organisation │ │ │ · Membres │ │ │ · Clés API │ │ │ ───────────────────────────── │ │ │ 👤 Utilisateur [⋮] │ │ └──────────────────────────────────────────────────────────────┘ ``` ### 3.2 Décisions | Décision | Avant | Après | Motif | |----------|-------|-------|-------| | **Suppression du double titre** | Topbar affiche le nom de nav + page affiche son `

` | Topbar affiche le **breadcrumb** ; la page seule porte le `

` | Corrige A5 | | **Sidebar repliable** | `w-64` fixe | `w-60` / `w-16` replié, persisté en `localStorage` | Rend 240px aux tables larges | | **Groupes de navigation** | 8 entrées à plat | 3 groupes (Pilotage / Ressources / Organisation) avec libellés `text-label` | Lisibilité, prépare la croissance | | **Paramètres regroupés** | 3 entrées de nav dispersées | 1 entrée + sous-navigation | Corrige la dispersion relevée en B2 | | **Un seul avatar** | Sidebar + topbar | Pied de sidebar uniquement, avec menu (Profil / Déconnexion) | Corrige la redondance | | **Logout dans le menu** | Bouton rouge pleine largeur permanent | Entrée du menu utilisateur | Poids visuel proportionné | | **Command menu ⌘K** | Absent | Recherche globale : navigation, réservations, ports, actions | Standard SaaS attendu | | **Bottom-nav mobile** | 5 entrées sur 8 | 4 entrées + « Plus » ouvrant le drawer complet | Aucune section inaccessible | | **Shell mutualisé** | 2 layouts dupliqués à 80 % | `AppShell` paramétré (`variant: 'app' | 'admin'`) | Corrige D2 | | **Icônes** | SVG inline manuscrits | `Menu`, `X`, `PanelLeftClose` de lucide | Cohérence | **Variante admin :** même `AppShell`, `variant="admin"` → sidebar `bg-brand-navy text-white`, logo blanc, séparateurs `border-white/10`. Le contenu des pages admin adopte le même vocabulaire que le dashboard (correction de la rupture chrome/contenu relevée en B3). ### 3.3 États de l'item de navigation | État | Style | |------|-------| | Défaut | `text-neutral-700 hover:bg-neutral-100 hover:text-brand-navy` | | Actif | `bg-neutral-100 text-brand-navy font-semibold` + barre `w-0.5 bg-brand-turquoise` à gauche | | Verrouillé (plan) | `text-neutral-400` + icône `Lock` + `Tooltip` expliquant le plan requis, lien `/pricing` | | Replié | icône seule centrée + `Tooltip` au survol | > L'état actif abandonne le fond bleu au profit d'un fond neutre + **accent turquoise en filet**. Plus discret, plus précis, strictement dans la charte. --- ## 4. Composants de navigation | Composant | Rôle | Notes d'implémentation | |-----------|------|------------------------| | `AppShell` | Enveloppe sidebar + topbar + contenu + bottom-nav | Remplace les 2 layouts | | `Sidebar` | Navigation groupée, repliable, drawer sous `lg` | Focus trap en mode drawer | | `Topbar` | Breadcrumb + ⌘K + notifications + langue + avatar | `h-14`, `sticky`, `border-b` | | `Breadcrumb` | Fil d'Ariane dérivé de la route + libellés i18n | Tronque au milieu sur mobile | | `PageHeader` | Titre `h3`, description, onglets, actions | **Extension** de l'existant (déjà sur 9 pages) | | `Tabs` | Sous-navigation de page (paramètres, détail réservation) | Sur `@radix-ui/react-tabs` (installé) | | `CommandMenu` | Palette ⌘K | Sur `ui/command.tsx` complété | | `BottomNav` | Navigation mobile 4 + « Plus » | — | --- ## 5. Composants de contenu ### 5.1 `DataTable` — pièce maîtresse Fondé sur `@tanstack/react-table` v8 (installé, utilisé une seule fois) et `@tanstack/react-virtual` (installé, jamais utilisé). | Capacité | Détail | |----------|--------| | Colonnes | Définition déclarative, tri, redimensionnement, visibilité | | Densité | `compact` (`py-3`) par défaut / `comfortable` (`py-4`) | | Sélection | Cases à cocher + barre d'actions groupées flottante | | En-tête | `sticky top-0`, `text-label`, fond `neutral-50` | | Ligne | `hover:bg-neutral-50`, sélectionnée `bg-neutral-100` | | Colonne d'actions | `sticky right-0`, menu sur `@radix-ui/react-dropdown-menu` — **remplace le positionnement manuel `menuPos`** relevé en B2 | | **Responsive** | ≥ `lg` : table · `md` : colonnes secondaires masquées · < `md` : **liste de `DataCard`** (titre, 3 champs clés, menu d'actions) | | Virtualisation | Activable, pour `/admin/logs` et les résultats de recherche | | États | `loading` → `TableSkeleton` · `empty` → `EmptyState` · `error` → `ErrorState` | | Pagination | `Pagination` intégré, taille de page persistée | Ce composant absorbe **26 tables brutes, 7 paginations et 21 `overflow-x-auto`**. ### 5.2 Autres | Composant | Rôle | |-----------|------| | `Card` | Rectifié : `border` seul, `p-5`, `CardTitle` en `text-h5` | | `StatCard` | KPI : libellé `text-label`, valeur `text-h2`, delta, icône discrète. **Aligné à gauche.** | | `DataCard` | Représentation mobile d'une ligne de table | | `Badge` | Variants sémantiques : `neutral` `info` `success` `warning` `danger` — tokens de charte uniquement | | `StatusBadge` | Conservé (badges d'abonnement Silver/Gold/Platinium) | | `Callout` | Encadré éditorial : `info` `warning` `success` `danger` — absorbe les ~30 encadrés du wiki | | `Pagination` | Précédent/Suivant + pages + sélecteur de taille + compteur | | `DescriptionList` | Paires libellé/valeur des pages de détail | | `Timeline` | Suivi d'expédition (`/track-trace`), étapes de réservation | --- ## 6. Composants de saisie | Composant | Base | Correction apportée | |-----------|------|---------------------| | `Button` | `cva` + `cn()` + `@radix-ui/react-slot` | `asChild` (corrige le `