expria-frontend/docs/adr/006-stack-versions-2026.md
Hermann_Kitio b68f160bce feat(design-system): reskin Charcoal — tokens dark-default + sidebar navy permanent
- Remplacement intégral index.css par palette Charcoal (DESIGN_SYSTEM.md v2.0)
- Dark = thème par défaut, .light = override via @custom-variant light
- Sidebar navy #0C1528 permanent (identique dark+light)
- Script anti-FOUC inline dans index.html
- Layout : radial-gradient sur <main>, sidebar 230px, max-w-[1100px]
- Renommage tokens Boréal→Charcoal sur ~45 composants
- Inversion dark: → baseline + light: sur primitives shadcn
- Fix logo blanc forcé dans sidebar
- ADR 006 mis à jour

Typecheck: OK · Tests: 122/122 

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 23:09:15 +03:00

292 lines
12 KiB
Markdown

# ADR 006 — Stack frontend : versions 2026 (React 19, Vite 8, TypeScript 6, Tailwind 4, RR7)
**Statut :** Accepté — mis à jour Sprint 0.5
**Date :** 2026-04-17
**Décideur :** Hermann
**Contexte :** Révélé par l'état des lieux Claude Code au démarrage du Sprint 0 frontend
---
## Contexte
La première version d'`ARCHITECTURE.md` §2 listait une stack basée sur les versions "connues stables" :
- React 18
- Vite 5
- TypeScript 5
- Tailwind 3
- React Router v6
L'état des lieux effectué par Claude Code au démarrage du Sprint 0 (2026-04-17) a révélé que le scaffold installé plusieurs semaines auparavant utilisait des versions plus récentes :
- React 19.2.4
- Vite 8.0.4
- TypeScript 6.0.2
- Tailwind 4.2.2
- React Router v7.14.1
Cette divergence doit être résolue : soit downgrader le scaffold, soit mettre à jour la documentation.
## Options envisagées
### Option A — Downgrader vers les versions de la doc originale
Aligner le scaffold sur React 18, Vite 5, TypeScript 5, Tailwind 3, React Router v6.
- **Avantages :** documentation historique respectée, versions "éprouvées" en production.
- **Inconvénients :**
- Casse un `node_modules` qui fonctionne
- Perd l'optimisation du compilateur React 19 (Actions, useOptimistic)
- Perd le moteur Oxide de Tailwind 4 (builds 3,5x plus rapides)
- Perd le typage strict amélioré de TypeScript 6
- Downgrade effectué pour des raisons qui n'existent plus (les versions récentes sont matures en avril 2026)
### Option B — Mettre à jour la documentation
Accepter les versions installées et mettre à jour `ARCHITECTURE.md §2` pour refléter la réalité.
- **Avantages :**
- Préserve le travail de scaffold déjà fait
- Bénéficie des améliorations de performance des versions récentes
- Écosystème mature : shadcn/ui supporte complètement Tailwind 4 et React 19 depuis début 2025
- Alignement avec l'écosystème 2026 (les nouveaux tutoriels, docs, et ressources communautaires supposent ces versions)
- **Inconvénients :**
- Versions légèrement plus récentes = moins de StackOverflow disponible pour les cas exotiques
- Mitigation : Claude Opus 4.7 connaît bien ces versions (cf. knowledge cutoff janvier 2026)
### Option C — Hybride
Garder React 19, Vite 8, TypeScript 6 mais downgrader Tailwind 4 → 3 pour "compatibilité shadcn/ui classique".
- **Avantages :** apparemment plus prudent.
- **Inconvénients :** injustifié depuis que shadcn/ui supporte complètement Tailwind 4 avec configuration CSS-first via `@theme`. Ajoute de la complexité sans bénéfice.
## Décision
**Option B** — accepter les versions installées et mettre à jour la documentation.
### Stack frontend officielle au 2026-04-17
| Couche | Version | Notes |
|---|---|---|
| React | 19.2.x | Server Components N/A (SPA pur), Actions et useOptimistic disponibles |
| React DOM | 19.2.x | |
| Vite | 8.0.x | Moteur Rolldown stable, config simplifiée |
| TypeScript | 6.0.x | Typage strict activé (voir tsconfig.app.json) |
| Tailwind CSS | 4.2.x | Configuration CSS-first via `@theme`, pas de `tailwind.config.ts` |
| `@tailwindcss/vite` | 4.2.x | Plugin Vite officiel (préféré au plugin PostCSS) |
| React Router | v7.14.x | Compatible API v6, data loaders disponibles |
| Supabase JS | 2.103.x | |
### Dépendances à ajouter lors du scaffold
| Package | Rôle | Cf. ADR |
|---|---|---|
| `@tanstack/react-query` | Cache serveur, refetch, mutations | ARCHITECTURE.md §2 |
| `zod` | Validation des inputs formulaires | SECURITY.md SEC-04 |
| `react-markdown` | Rendu sécurisé des rapports IA | SECURITY.md SEC-05 |
| `class-variance-authority`, `clsx`, `tailwind-merge` | Utilitaires shadcn/ui | — |
| `lucide-react` | Icônes (standard shadcn/ui) | — |
| Packages `@radix-ui/react-*` | Primitives shadcn/ui (installés à la demande) | — |
| `@sentry/react` | Monitoring | TECH_DEBT.md FTD-07 (après MVP) |
### Dépendances de développement
| Package | Rôle |
|---|---|
| `vitest` | Tests unitaires |
| `@vitest/coverage-v8` | Couverture |
| `@testing-library/react` | Tests React |
| `@testing-library/jest-dom` | Matchers DOM |
| `@testing-library/user-event` | Simulation user |
| `jsdom` | Environnement DOM pour Vitest |
| `prettier` | Formatage |
| `eslint-config-prettier` | Intégration ESLint ↔ Prettier |
### Configuration Tailwind 4
Pas de `tailwind.config.ts`. La configuration se fait exclusivement dans `src/index.css`.
#### Mode thème (mis à jour Sprint DA Charcoal — 2026-04-24)
**Dark est le thème par défaut.** Les tokens de contenu (`--color-canvas`, `--color-ink-*`, etc.) sont déclarés en mode dark dans `@theme`. Une classe `.light` sur `<html>` active le mode clair en override. Configuré via :
```css
@custom-variant light (&:where(.light, .light *));
```
Ce variant permet d'écrire `light:bg-surface` dans les composants quand un comportement spécifique au mode clair est requis (ex. primitives shadcn où l'opacité doit être adaptée).
#### Tokens @theme (DA Charcoal — validée Sprint DA Charcoal 2026-04-24)
```css
@import 'tailwindcss';
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap');
@custom-variant light (&:where(.light, .light *));
@theme {
/* ── Invariants (identiques dark + light) ── */
/* Sidebar navy permanent */
--color-sidebar-bg: #0C1528;
--color-sidebar-border: rgba(255, 255, 255, 0.07);
--color-sidebar-text: rgba(255, 255, 255, 0.6);
--color-sidebar-text-hover: rgba(255, 255, 255, 0.9);
--color-sidebar-text-active: #FFFFFF;
--color-sidebar-nav-hover: rgba(255, 255, 255, 0.07);
--color-sidebar-nav-active: rgba(255, 255, 255, 0.1);
--color-sidebar-section-label: rgba(255, 255, 255, 0.3);
/* Brand */
--color-brand: #1B4FD8;
--color-brand-hover: #1744B8;
--color-brand-active: #13379C;
--color-brand-dark: #1740B0;
--color-brand-ink: #FFFFFF;
/* Semantic (invariants) */
--color-warning: #F59E0B;
--color-warning-soft: rgba(245, 158, 11, 0.12);
--color-danger: #EF4444;
--color-danger-soft: rgba(239, 68, 68, 0.12);
/* Typographie */
--font-sans: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
--font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
/* Rayons (override Tailwind) */
--radius-xs: 6px; --radius-sm: 8px; --radius-md: 12px;
--radius-lg: 16px; --radius-xl: 20px; --radius-pill: 999px;
/* Focus */
--shadow-focus: 0 0 0 3px rgba(27, 79, 216, 0.18);
/* ── Dark mode (défaut) ── */
--color-canvas: #111111;
--color-surface: rgba(255, 255, 255, 0.035);
--color-surface-hover: rgba(255, 255, 255, 0.055);
--color-surface-solid: #1E1E1E;
--color-surface-raised: #222222;
--color-border: rgba(255, 255, 255, 0.06);
--color-border-strong: rgba(255, 255, 255, 0.12);
--color-ink-primary: #E5E5E5;
--color-ink-secondary: rgba(255, 255, 255, 0.55);
--color-ink-tertiary: rgba(255, 255, 255, 0.3);
--color-ink-inverse: #111111;
--color-brand-soft: rgba(27, 79, 216, 0.1);
--color-brand-text: #7DA4F0;
--color-success: #4ADE80;
--color-success-soft: rgba(74, 222, 128, 0.12);
--color-topbar-bg: rgba(17, 17, 17, 0.88);
--color-gradient-a: rgba(27, 79, 216, 0.05);
--color-gradient-b: rgba(27, 79, 216, 0.03);
--shadow-card: none;
--shadow-raised: none;
}
/* Light mode — override sur <html class="light"> */
.light {
--color-canvas: #F3F4F6;
--color-surface: #FFFFFF;
--color-surface-hover: #F8F9FB;
--color-surface-solid: #FFFFFF;
--color-surface-raised: #FFFFFF;
--color-border: rgba(0, 0, 0, 0.07);
--color-border-strong: rgba(0, 0, 0, 0.14);
--color-ink-primary: #0F0F1A;
--color-ink-secondary: rgba(0, 0, 0, 0.55);
--color-ink-tertiary: rgba(0, 0, 0, 0.3);
--color-ink-inverse: #FFFFFF;
--color-brand-soft: rgba(27, 79, 216, 0.06);
--color-brand-text: #1B4FD8;
--color-success: #16A34A;
--color-success-soft: rgba(22, 163, 74, 0.1);
--color-topbar-bg: rgba(243, 244, 246, 0.88);
--color-gradient-a: rgba(27, 79, 216, 0.025);
--color-gradient-b: rgba(27, 79, 216, 0.01);
--shadow-card: 0 1px 2px rgba(15, 18, 32, 0.04), 0 1px 8px rgba(15, 18, 32, 0.03);
--shadow-raised: 0 4px 16px rgba(15, 18, 32, 0.06), 0 1px 2px rgba(15, 18, 32, 0.04);
}
```
#### Classes Tailwind générées
Les tokens `@theme` créent des classes utilitaires directement utilisables :
| Token | Classes Tailwind |
|---|---|
| `--color-canvas` | `bg-canvas`, `text-canvas`, `border-canvas` |
| `--color-surface` | `bg-surface`, `border-surface` |
| `--color-surface-hover` | `bg-surface-hover` |
| `--color-sidebar-bg` | `bg-sidebar-bg` (navy permanent, identique dark+light) |
| `--color-ink-primary` | `text-ink-primary` |
| `--color-ink-secondary` | `text-ink-secondary` |
| `--color-ink-tertiary` | `text-ink-tertiary` |
| `--color-brand` | `bg-brand`, `border-brand`, `ring-brand` |
| `--color-brand-text` | `text-brand-text` (bleu adapté au fond — `#7DA4F0` dark, `#1B4FD8` light) |
| `--color-brand-soft` | `bg-brand-soft` (teinte chip / highlight discret) |
| `--color-success-soft`, `-warning-soft`, `-danger-soft` | `bg-success-soft`, etc. |
| `--shadow-card`, `--shadow-raised` | `shadow-card`, `shadow-raised` (auto dual-theme : `none` en dark, ombre en light) |
| `--shadow-focus` | `shadow-focus` (halo bleu 3px sur `:focus-visible`) |
**Conventions critiques :**
- `bg-surface` = cards / modals / panels. `bg-canvas` = fond de page. Ne jamais inverser.
- `bg-sidebar-bg` = navy permanent — ne change jamais entre dark et light (ancre visuelle de marque).
- Utiliser le préfixe `light:` uniquement quand un override spécifique au mode clair est strictement nécessaire (ex. primitives shadcn où l'opacité d'une couleur sémantique diffère).
#### Typographie
Plus Jakarta Sans chargée via Google Fonts dans `index.html` (preconnect + stylesheet, weights 400/500/600/700). Migration vers auto-hébergement (`@fontsource/plus-jakarta-sans`) après MVP si les performances réseau deviennent un enjeu.
### shadcn/ui avec Tailwind 4
La CLI shadcn/ui supporte Tailwind 4 depuis début 2025 :
```bash
npx shadcn@latest init
npx shadcn@latest add button dialog form
```
Les composants générés utilisent les conventions Tailwind 4 (pas de `forwardRef`, attributs `data-slot`). Le fichier de configuration reste `components.json` à la racine.
## Conséquences
**Positives :**
- Pas de perte de travail sur le scaffold existant
- Performances optimales (build Tailwind 4 : microsecondes sur builds incrémentaux)
- Stack aligné sur l'écosystème 2026 — facile pour un dev externe qui arrivera
- Compilateur React 19 apporte des optimisations gratuites
**Négatives :**
- Les versions récentes peuvent avoir quelques bugs non encore découverts. Mitigation : mise à jour ponctuelle vers la dernière version patch en cas de bug signalé (ex : 19.2.4 → 19.2.5).
- Si un dev arrive avec une expertise sur React 17/18 uniquement, courbe d'apprentissage légère. Mitigation : `ONBOARDING.md` liste les ressources officielles pour React 19 et Tailwind 4.
**À revisiter si :**
- Une faille de sécurité critique apparaît dans une version spécifique
- Une incompatibilité bloquante est découverte entre deux packages (peu probable en avril 2026)
## Actions de mise en cohérence
1. Mettre à jour `ARCHITECTURE.md §2` avec les versions ci-dessus (réalisé en session actuelle)
2. Mettre à jour `ONBOARDING.md` pour référencer React 19 et Tailwind 4 dans les ressources (à faire)
3. Aucune action sur `TESTS_AUTOMATISES.md` — Vitest fonctionne identiquement
4. Aucune action sur les ADRs 001-005 — ils ne référencent pas de versions précises
## Références
- État des lieux Claude Code du 2026-04-17
- [shadcn/ui Tailwind v4](https://ui.shadcn.com/docs/tailwind-v4) — support officiel confirmé
- [React 19 Upgrade Guide](https://react.dev/blog/2024/04/25/react-19)
- [Tailwind CSS v4.0](https://tailwindcss.com/blog/tailwindcss-v4)
- `ARCHITECTURE.md` §2 (mis à jour en parallèle)