Triage et intégration des propositions frontend du buffer 95_a_capitaliser.md (lot local RL799_V2/Vue3 + app-alexandrie/RN-Expo, mai-juin 2026). ~73 entrées intégrées sur knowledge/frontend/ + 1 nouveau fichier, dont : - patterns/state.md : race-token partagé latest-wins (fusion 3 props), capture sync anti-race, event bus timestamp, clé cache composite, état dérivé = computed - risques/state.md : 9 risques Zustand/store (fetchId reset, useRef remount, re-fetch infini sur [], flag optimiste écrasé, cache détail/liste stale, latch sans reset, :key index) - patterns/navigation.md : Expo Router (tab bar, useFocusEffect, Href typé, routing pur fusionné) - patterns/general.md : helpers temps purs, composants génériques + skeleton, fail-fast, touch target - risques/general.md : 24 risques (sweep statique, filtre client liste paginée, hooks avant return, a11y VoiceOver/disabled, redirection allowlist, RangeError toISOString, section i18n...) - design-tokens (cluster theming light/dark MD3), tests, performance, react-native, nextjs - NOUVEAU risques/responsive.md (gating par capacité d'input + checklist régressions mobile) - READMEs patterns/risques mis à jour Doublons inter-fichiers évités (vérifié : aucune ancre dupliquée introduite). Rejets (doublons 91/9/87), reciblages workflow (156/257) et bloc 32 (CLAUDE projet) non intégrés ici. Source 95_a_capitaliser.md non purgée (purge en fin de capitalisation complète). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
11 KiB
Frontend — Risques & vigilance : Design Tokens
Extrait de la base de connaissance Lead_tech. Voir
knowledge/frontend/risques/README.mdpour l'index complet.
Double système d'espacement dans un monorepo Expo
Risques
- Deux échelles d'espacement coexistent avec des noms différents pour des valeurs identiques (
Spacing.three = 16vsspacing.base = 16) - L'audit "zéro hardcode" ne détecte pas l'inconsistance car les deux sont des constantes nommées
- Les deux échelles peuvent diverger silencieusement
Symptômes
import { Spacing } from '@/constants/theme'coexiste avecimport { spacing } from '@/theme'- Certains screens refactorisés utilisent l'ancien système sans que personne ne le détecte
Bonnes pratiques / mitigations
- Dès la création de
src/theme/spacing.ts, supprimer ou viderconstants/theme.ts(sauf constantes vraiment spécifiques :MaxContentWidth,BottomTabInset) - Faire un
grep from '@/constants/theme'à chaque story pour détecter les usages résiduels - Cause racine : le template Expo génère
constants/theme.tsavecSpacing = { one, two, three... }— à purger explicitement lors de la story design tokens - Contexte technique : Expo / React Native — app-alexandrie story 0.5, 19-03-2026
Dimensions d'image via tokens spacing (React Native)
Risques
- Si
spacing.hugechange pour une raison d'espacement, la taille de l'image change silencieusement - Régression visuelle sans que personne ne réalise l'impact — les deux changements semblent indépendants
Symptômes
width: spacing.huge, height: spacing.hugepour une image dont la taille est fixée par la spec Figma
Bonnes pratiques / mitigations
// Correct : constante locale ou token dédié
const THUMBNAIL_SIZE = 48; // Figma spec node 1-16147
// OU token dans un fichier sizes.ts dédié si la valeur est partagée
export const sizes = { thumbnail: 48, avatar: 40 } as const;
Règle : spacing = espacement entre éléments. sizes ou constantes locales = dimensions de composants.
- Contexte technique : React Native / design tokens — app-alexandrie story 0.4, 19-03-2026
Inline styles dans les composants dashboard
Risques
- Contourne le système Tailwind + tokens CSS
- Crée des incohérences visuelles non détectées par le linter
Symptômes
style={{ color: '#123456', marginTop: 8 }}dans un composant dashboard
Bonnes pratiques / mitigations
-
Bloquer en code review systématiquement tout
style={{...}}dans les composants dashboard -
Exception acceptable uniquement : animations CSS dynamiques (valeurs calculées au runtime)
-
Contexte technique : React / Tailwind — app-template-resto 22-03-2026
Classes Tailwind invalides courantes (bugs silencieux)
Risques
- Classes Tailwind invalides sont silencieusement ignorées — aucun warning, comportement visuellement cassé
Symptômes
- Item masqué affiché à pleine opacité (
opacity-55→ invalide) - Largeur incorrecte (
w-35→ invalide)
Bonnes pratiques / mitigations
Erreurs courantes :
-
opacity-55→ invalide. Scale : 0/5/10/20/25/30/40/50/60/70/75/80/90/95/100 → utiliseropacity-50ouopacity-60 -
w-35→ invalide. Scale saute dew-32àw-36→ utiliserw-36 -
box-border→ redondant. Tailwind Preflight applique déjàbox-sizing: border-boxglobalement -
Toujours vérifier les classes custom/non-standard avec l'extension Tailwind IntelliSense
-
Contexte technique : Tailwind CSS — app-template-resto 22-03-2026
Imports morts de tokens dans les composants React Native
Risques
- Les imports de tokens abandonnés (ex :
fontWeightaprès passage aux fontes nommées par variante) ne génèrent pas d'erreur TypeScript car le type est compatible avec les usages implicites - La migration de design system peut laisser des dépendances obsolètes indétectables au build
Symptômes
import { fontWeight } from '@/tokens'présent mais inutilisé — aucun lint warning sans règle dédiée- Tokens refactorisés encore référencés dans des composants après migration
Bonnes pratiques / mitigations
- Activer
@typescript-eslint/no-unused-varsetno-unused-importsdans la config ESLint mobile - Lors de toute migration de tokens, auditer les imports de chaque composant UI concerné
- Contexte technique : React Native / ESLint — app-alexandrie, 25-03-2026
Fallbacks de tokens incohérents avec le thème actif
Risques
- Composants lisibles en dev mais illisibles quand une variable manque en production.
Symptômes
- Fallback hardcodé light-theme dans un contexte dark-theme.
Bonnes pratiques / mitigations
-
Utiliser des fallbacks cohérents avec le thème de référence.
-
Préférer un fallback vers alias sémantique existant plutôt qu'une couleur brute.
-
Contexte technique : design tokens / thèmes CSS — RL799_V2 10-04-2026
Variables CSS utilisées mais non définies (fallback silencieux)
Risques
- Dérive invisible du design system (les fallbacks masquent les oublis de token).
Symptômes
- L'UI semble correcte mais contourne les tokens sur une part significative des règles.
Bonnes pratiques / mitigations
-
Auditer régulièrement : variables utilisées moins variables définies.
-
Traiter chaque variable non définie comme dette explicite.
-
Contexte technique : design tokens / audit CSS vars — RL799_V2 17-04-2026
Généralisation : token inexistant sans fallback = propriété silencieusement non appliquée
- Le piège vaut pour toutes les familles de tokens, pas seulement la scale d'espacement (
--rm-space-0-5). Cas traître :border: 1px solid var(--rm-color-border-subtle)quand le token n'existe pas et n'a pas de 2ᵉ argument de fallback →border-colorretombe sur sa valeur initialecurrentColor(couleur du texte) : la bordure s'affiche mais avec la mauvaise couleur, encore plus discret qu'une bordure absente. - Règle : avant d'utiliser un nom de token "par analogie" (
-subtle,-muted,-faint), grep le nom EXACT dans le fichier de thème (grep -- '--rm-color-border-subtle:' theme.css). La nomenclature n'est pas devinable (RL799 aborder-base/strong/soft/panel/accent, PASsubtle). - Un token fantôme déjà présent dans N autres fichiers n'est PAS une excuse : il propage le bug. Le corriger ponctuellement + noter la dette pour un nettoyage transverse.
- Détection review : pour chaque
var(--rm-…)SANS 2ᵉ argument dans un fichier touché, vérifier l'existence de la définition. - Contexte technique : Vue 3 / CSS — RL799 (code review v2-2-1,
border-subtle→border-soft), 18-06-2026
Theming light/dark : pièges cachés invisibles aux tests unitaires
Risques
- La majorité des bugs de migration light/dark ne sont visibles qu'au smoke device : typecheck, lint et tests unitaires passent sans warning
- Trois familles de causes : composants tiers non thématisés,
<Text>/<TextInput>sans couleur explicite, et mauvaise résolution du scheme effectif
Symptômes
- Écran 80 % migré mais un bloc reste noir/illisible en dark
- Texte ou placeholder invisible sur fond sombre malgré le remplacement de tous les hex
Bonnes pratiques / mitigations
- Composants tiers (Markdown, charts, WebView) : ils appliquent leurs styles par défaut (
color: '#000') qui n'héritent ni de React Navigation ni du hook. Passer un objetstylemappant explicitement aux tokens (body,paragraph,link,blockquote,code_inline). Détection :grep -rln "Markdown\|svg-charts\|WebView". <Text>sanscolor:: en RN Web, hérite du défaut OS → invisible sur fond sombre. Détection :grep -nB1 "<Text" file.tsx | grep -v "color:". Ajoutercolor: themed.onSurface(ouonSurfaceVariantpour metadata).<TextInput>sur RN Web :colorETplaceholderTextColorsont obligatoires ensemble, sinon input/placeholder illisibles en dark.- Préférence
'system'+ toggle binaire :isDark = preference === 'dark'est faux quandpreference === 'system'+ OS dark (rendu dark maisisDark === false). UtiliserisDark = useEffectiveColorScheme() === 'dark'(refléter le rendu effectif, pas la préférence brute). ThemeProviderReact Navigation :DefaultTheme/DarkThemeposent leurscolors.card/textau-dessus des composants. Construire unThemecustom à partir des tokens (background,card,text,border,notification).- Anti-pattern global : laisser le smoke device comme seul filet. Le filet préventif est un grep méthodique post-migration.
- Contexte technique : React Native / Expo — app-alexandrie (ux-cleanup-8), 29-05-2026
Nouveau site colors.X introduit pendant une migration useThemedColors
Risques
- Pendant qu'une story migre vers
useThemedColors(light/dark), une autre story crée un nouveau fichier qui utiliseimport { colors } from '@/theme'(palette dark figée) +backgroundColor: colors.background - Typecheck et tests passent ; le mode light cassé n'est visible qu'à l'œil. Dette héritée par la story de migration
Symptômes
+not-found.tsxcréé pendant une migration utilisecolors.Xau lieu dec.X(résultat deuseThemedColors)
Bonnes pratiques / mitigations
- Toute story qui crée un nouveau fichier de rendu pendant une migration thème active utilise
useThemedColorsd'office, même hors scope de la migration - Review : grep
from '@/theme'sur les fichiers ajoutés du diff ;colors.Xau lieu dec.X= finding HIGH - Idéalement : ESLint
no-restricted-importsinterdisant l'import nommécolorsdepuis@/themedanssrc/app/etsrc/components/(sauf opt-out commenté) - Contexte technique : React Native — app-alexandrie (ux-cleanup-4,
+not-found.tsx), 29-05-2026
Hook themed sans consommateur = mort-né
Risques
- Introduire
useThemedXxx()(couleurs, shadows, typo) sans migrer aucun caller dans le même commit : le hook est invisible à la review (aucun diff ne montre son usage) - Les composants
import { xxx } from '@/theme'restent en static (= dark en light) ; la prochaine PR ré-écrit en static croyant que c'est la convention
Symptômes
use-themed-shadows.tslivré avec 0 caller pendant 4 commits ; 3 callers importaient encoreshadows.buttonstatic
Bonnes pratiques / mitigations
- Un PR qui ajoute un hook themed DOIT migrer ≥ 1 consommateur réel + ajouter un test prouvant la différence light/dark (
shadowsLight.card.shadowColor !== shadowsDark.card.shadowColor) - Contexte technique : React Native — app-alexandrie (ux-cleanup-8), 29-05-2026