BRI-304 — Table de correspondance tokens Figma ↔ code (V0)¶
Livrable V0 : comparaison manuelle des tokens couleur + typo (Figma vs Tailwind/Uniwind). Critère de succès : les drifts identifiés sont réels et actionnables. Côté Figma : extrait le 2026-06-11 via MCP
search_design_systemsur la lib 🎨 Uimmo (yEPrXyd3donmRXv4K7kHtN). Côté code : à remplir avec le lead dev front au kick-off.Légende statut : ✅ aligné · ⚠️ nom différent (même valeur) · 🎯 valeur différente · ❌ absent d'un côté · ❓ à vérifier
⚠️ À lire avant la réunion — 2 constats d'extraction¶
1. search_design_system donne les noms + clés + scopes, PAS les valeurs hex résolues.
Pour extraire la valeur d'un token, il faut get_variable_defs(fileKey, nodeId) sur un nœud qui l'utilise → l'extracteur Figma du cron devra passer par là (ou l'API REST /variables). À acter comme contrainte technique. La colonne « valeur Figma » ci-dessous n'est remplie que là où on la connaît déjà (BRI-299) ; le reste = → get_variable_defs.
2. La clé (key) est l'identifiant stable, le nom dérive.
Chaque variable a une key immuable. Le matching le plus robuste côté Figma se fait par key, pas par nom (le nom peut être renommé → c'est justement un drift). Le code n'a pas ces clés → pour le pont Figma↔code, le matching restera par convention de nommage, d'où l'importance d'une convention partagée.
🔴 Drifts DÉJÀ repérés côté Figma (avant même de regarder le code)¶
Trouvés pendant l'extraction. Ce sont des incohérences internes à Uimmo — donc des faux-négatifs garantis pour un matching naïf par nom. À montrer au lead dev : ça illustre concrètement pourquoi le sujet existe.
| # | Drift | Détail | Impact matching |
|---|---|---|---|
| D1 | Casse incohérente | Bricks specific/brandborder500 (b minuscule) vs brandBorder300 / brandBorder400 (B majuscule) |
Un match exact sur nom rate brandborder500 |
| D2 | Structure d'état incohérente | Info state a infoBorder600 et infoBorder950 (bordures numérotées) alors que Success/Alert/Pending ont un seul xxxBorder non numéroté |
Le moteur doit gérer des schémas par état différents |
| D3 | Doublon / orphelin | infoBackground950 existe 2 fois : Info state/infoBackground950 (dans le groupe) et infoBackground950 tout court (hors groupe, Colors/color/infoBackground950) |
Doublon réel à nettoyer dans Figma |
| D4 | Même nom, 2 collections | Core/white existe dans la collection Colors (ea000bcf…) et dans Primitives (ed47f31a…) |
Lequel est la source ? Ambiguïté de matching |
| D5 | Pollution legacy WebApp | Les recherches remontent aussi la lib 🖥️ WebApp (colors/white, Text/md/md - Medium, gray-secondary…) |
L'extracteur doit filtrer sur libraryKey Uimmo sinon faux drifts massifs |
| D6 | Surcharge sémantique | Disabled state/disabledBackground sert à la fois border-non-cliquable et background (cf. description) ; disabledText a un scope quasi ALL |
Un token = plusieurs rôles → matching 1:1 code difficile |
👉 Ces 6 points sont des drifts réels et actionnables = on a déjà à moitié rempli le critère de succès V0, sans même avoir ouvert le code.
1. Couleurs (collection « Colors », lib Uimmo)¶
Valeurs hex : seules celles connues via BRI-299 sont indiquées ; les autres →
get_variable_defs.
Marque (Bricks specific)¶
| Nom Figma | key Figma |
Valeur Figma | Nom code | Valeur code | Statut |
|---|---|---|---|---|---|
Bricks specific/brandText |
795b15c9… |
#ec5223 |
❓ | ||
Bricks specific/brandBackground50 |
75faca62… |
→ get_variable_defs | ❓ | ||
Bricks specific/brandBackground100 |
2ab7fe8c… |
#fde6d7 |
❓ | ||
Bricks specific/brandBackground200 |
3419dbc4… |
→ | ❓ | ||
Bricks specific/brandBackground300 |
601c1c2d… |
→ | ❓ | ||
Bricks specific/brandBackground400 |
56cd619e… |
#f07141 |
❓ | ||
Bricks specific/brandBackground500 |
afb4cc24… |
→ | ❓ | ||
Bricks specific/brandBorder300 |
b06e1d09… |
→ | ❓ | ||
Bricks specific/brandBorder400 |
f2c6435e… |
→ | ❓ | ||
Bricks specific/brandborder500 ⚠️D1 |
ac5bb2b4… |
→ | ⚠️ |
Typographie (couleurs de texte)¶
| Nom Figma | key Figma |
Valeur Figma | Nom code | Valeur code | Statut |
|---|---|---|---|---|---|
Typography/defaultHeading |
111c24f5… |
#13273e |
❓ | ||
Typography/defaultText |
3ed5eb32… |
#76818b |
❓ |
Core¶
| Nom Figma | key Figma |
Valeur Figma | Nom code | Valeur code | Statut |
|---|---|---|---|---|---|
Core/white (Colors) ⚠️D4 |
ea000bcf… |
#ffffff |
⚠️ | ||
Core/white (Primitives) ⚠️D4 |
ed47f31a… |
#ffffff ? |
⚠️ | ||
Core/appBackground |
bb89c9d8… |
→ | ❓ |
Bordures & fonds neutres¶
| Nom Figma | key Figma |
Valeur Figma | Nom code | Valeur code | Statut |
|---|---|---|---|---|---|
Borders/nonInteractiveBorder |
334f7ab4… |
#eceae8 |
❓ | ||
Borders/interactiveBorder |
(à requêter) | #dbd9d7 |
❓ | ||
Backgrounds/neutralBackground50 |
be36abfc… |
#faf9f8 |
❓ | ||
Backgrounds/neutralBackground100 |
c8e43ebb… |
→ | ❓ | ||
Backgrounds/neutralBackground200 |
51369555… |
→ | ❓ | ||
Backgrounds/neutralBackground300 |
dbade9ff… |
→ | ❓ | ||
Backgrounds/neutralBackground400 |
79f7aa66… |
#c7c7c7 |
❓ |
État Success (rampe complète : Text · Border · Background 50→950)¶
| Nom Figma | key Figma |
Nom code | Statut |
|---|---|---|---|
Success state/successText |
8e687ab4… |
❓ | |
Success state/successBorder |
a16efae3… |
❓ | |
Success state/successBackground50 |
ca473beb… |
❓ | |
Success state/successBackground100 |
e32e2a87… |
❓ | |
Success state/successBackground200 |
25587891… |
❓ | |
Success state/successBackground300 |
fe116d30… |
❓ | |
Success state/successBackground400 |
63bf111d… |
❓ | |
Success state/successBackground500 |
4c9c130f… |
❓ | |
Success state/successBackground600 |
13db70a5… |
❓ | |
Success state/successBackground700 |
d2b8f258… |
❓ | |
Success state/successBackground800 |
4c16c89b… |
❓ | |
Success state/successBackground900 |
f59cf3e1… |
❓ | |
Success state/successBackground950 |
b46d2a22… |
❓ |
Valeur de base connue :
successText ≈ #16b374.
État Alert (rampe complète)¶
| Nom Figma | key Figma |
Nom code | Statut |
|---|---|---|---|
Alert state/alertText |
cf24c5dd… |
❓ | |
Alert state/alertBorder |
2e34d06d… |
❓ | |
Alert state/alertBackground50 |
9cd9b85c… |
❓ | |
Alert state/alertBackground100 |
841c92b0… |
❓ | |
Alert state/alertBackground200 |
21751c1a… |
❓ | |
Alert state/alertBackground300 |
ff7e64e4… |
❓ | |
Alert state/alertBackground400 |
22512f24… |
❓ | |
Alert state/alertBackground500 |
1dc9817a… |
❓ | |
Alert state/alertBackground600 |
d72a5e58… |
❓ | |
Alert state/alertBackground700 |
a05d0678… |
❓ | |
Alert state/alertBackground800 |
9d66e935… |
❓ | |
Alert state/alertBackground900 |
3bd3a0a7… |
❓ | |
Alert state/alertBackground950 |
f0ef9177… |
❓ |
Valeur de base connue :
alertText ≈ #d72746.
État Info (⚠️ structure différente — D2/D3)¶
| Nom Figma | key Figma |
Nom code | Statut |
|---|---|---|---|
Info state/infoText |
3e667244… |
❓ | |
Info state/infoBorder600 ⚠️D2 |
c5674a4e… |
⚠️ | |
Info state/infoBorder950 ⚠️D2 |
06ed436b… |
⚠️ | |
Info state/infoBackground50 |
246d2852… |
❓ | |
Info state/infoBackground100 |
d9264243… |
❓ | |
Info state/infoBackground300 |
3ac5fb50… |
❓ | |
Info state/infoBackground400 |
4ceb35ab… |
❓ | |
Info state/infoBackground500 |
d231bc94… |
❓ | |
Info state/infoBackground600 |
15d98900… |
❓ | |
Info state/infoBackground700 |
b644c0c0… |
❓ | |
Info state/infoBackground800 |
6c374857… |
❓ | |
Info state/infoBackground900 |
085150ae… |
❓ | |
Info state/infoBackground950 ⚠️D3 |
9ae0b98e… |
⚠️ | |
infoBackground950 (orphelin) ⚠️D3 |
ad1d9eb8… |
🔴 |
Valeur de base connue :
infoText ≈ #3280c2. Pas de palier 200 visible (à confirmer).
État Pending (rampe complète)¶
| Nom Figma | key Figma |
Nom code | Statut |
|---|---|---|---|
Pending state/pendingText |
71d1d1f4… |
❓ | |
Pending state/pendingBorder |
27f593bf… |
❓ | |
Pending state/pendingBackground50 |
74d9ed24… |
❓ | |
Pending state/pendingBackground100 |
79680472… |
❓ | |
Pending state/pendingBackground200 |
13678d78… |
❓ | |
Pending state/pendingBackground300 |
4539a7c9… |
❓ | |
Pending state/pendingBackground400 |
7ba56520… |
❓ | |
Pending state/pendingBackground500 |
996f6cbd… |
❓ | |
Pending state/pendingBackground600 |
7ddb3981… |
❓ | |
Pending state/pendingBackground700 |
36e960d3… |
❓ | |
Pending state/pendingBackground800 |
5f04bdf5… |
❓ | |
Pending state/pendingBackground900 |
12a83007… |
❓ | |
Pending state/pendingBackground950 |
f527bd0b… |
❓ |
Valeur de base connue :
pendingText ≈ #a66be1.
État Disabled (⚠️ surcharge sémantique — D6)¶
| Nom Figma | key Figma |
Nom code | Statut |
|---|---|---|---|
Disabled state/disabledText ⚠️D6 |
6da4d482… |
⚠️ | |
Disabled state/disabledBackground ⚠️D6 |
20e41808… |
⚠️ | |
Disabled state/disabledBorder |
ecf6c0a2… |
❓ |
Shiny (⚠️ rampe incomplète — un seul background)¶
| Nom Figma | key Figma |
Nom code | Statut |
|---|---|---|---|
Shiny/shinyText |
0e68accc… |
❓ | |
Shiny/shinyBorder |
0d2e51a4… |
❓ | |
Shiny/shinyBackground400 |
5669bd96… |
❓ |
Transparency (ghosts)¶
| Nom Figma | key Figma |
Nom code | Statut |
|---|---|---|---|
Transparency/ghost0 |
6d7f71ee… |
❓ | |
Transparency/ghost1 |
b81fe7eb… |
❓ | |
Transparency/ghost2 |
235b3727… |
❓ | |
Transparency/ghost3 |
68f773ab… |
❓ |
⚠️ Figma annonce ~85 variables Colors ; cette table couvre les groupes principaux. Compléter les paliers manquants (ex.
Infopalier 200,interactiveBorder) avant de figer le périmètre.
2. Typographie (styles de texte, lib Uimmo)¶
Police Inter. Heading = Semi Bold, Text = Medium. La couleur est portée séparément (cf. tokens couleur). Tailles : seules les connues sont indiquées.
Heading (9 styles)¶
| Style Figma | key Figma |
Taille connue | Nom code | Statut |
|---|---|---|---|---|
Heading/3xs |
0114a842… |
→ | ❓ | |
Heading/2xs |
98805acf… |
14 | ❓ | |
Heading/xs |
fae73ab8… |
16 | ❓ | |
Heading/sm |
5a85d6c1… |
18 | ❓ | |
Heading/md |
2411331a… |
→ | ❓ | |
Heading/lg |
314a507c… |
→ | ❓ | |
Heading/xl |
371900ab… |
→ | ❓ | |
Heading/2xl |
733bf7df… |
→ | ❓ | |
Heading/3xl |
99096772… |
→ | ❓ |
Text (4 styles)¶
| Style Figma | key Figma |
Taille connue | Nom code | Statut |
|---|---|---|---|---|
Text/xs |
02c3dcdf… |
→ | ❓ | |
Text/sm |
70aa1d8f… |
12 / w500 / lh~1.5 | ❓ | |
Text/md |
0815efb8… |
14 / w500 / lh~1.5 | ❓ | |
Text/lg |
995a2b1e… |
→ | ❓ |
⚠️ La lib legacy 🖥️ WebApp expose des styles homonymes mais nommés différemment (
Text/md/md - Medium,… - Semibold) → à exclure du périmètre (cf. drift D5).
3. Synthèse drift — état au 2026-06-11 (après publish Uimmo de Rémy)¶
| # | Catégorie | Drift | Action | Statut |
|---|---|---|---|---|
| D1 | Couleur | Casse brandborder500 |
renommé → brandBorder500 |
✅ corrigé |
| D3 | Couleur | infoBackground950 en double |
orphelin supprimé | ✅ corrigé |
| D6 | Couleur | Tokens disabled multi-rôles | scopes disabledText resserrés → [SHAPE_FILL, TEXT_FILL] + descriptions clarifiées |
✅ traité (non scindé, documenté) |
| D4 | Couleur | Core/white dans Colors + Primitives |
confirmé par Rémy : Colors/Core/white est un alias de la primitive |
✅ non-drift (architecture saine) |
| D2 | Couleur | Info : bordures numérotées (infoBorder600/950) vs single ailleurs |
décision Rémy : laissé tel quel (choix assumé) | ✅ clôturé (intentionnel) |
| D5 | Process | Lib WebApp legacy polluante | WebApp n'est plus du tout utilisée — pur legacy. Exclure côté extracteur ; candidate à l'archivage/dépublication | ➡️ hors Figma (cron) |
Bonus :
Info state/infoBackground200désormais présent (palier auparavant ❓).
Conclusion drifts internes Figma : tous traités. D1/D3/D6 corrigés ; D4 = alias légitime (non-drift) ; D2 = choix design assumé. Aucun drift interne Uimmo ouvert.
Score de sync V0 (indicatif, code) : ___ tokens alignés / ___ comparés = ___ % (à remplir avec le lead dev)
4. Côté code — extraction du 2026-08-18¶
Source :
~/Dev/monorepo/projects/common/front/theme/src/tailwind/uniwind-theme.css, auto-généré (« DO NOT EDIT ») depuis les fichiers TS du paquet@bricks-common-front/theme(colors/palette.ts,spacing.ts,border-radius.ts,fonts.ts). Contenu : 89 tokens couleur, 16 espacements (+6 conteneurs), 9 rayons, 5 ombres, 13 utilitaires de texte. Monorepo :brickssas/monorepo, branchedevelop, commit20a9cce.
4.1 La règle de correspondance est systématique¶
On supprime le groupe et on passe en kebab-case, avec le préfixe de famille :
| Figma | Code |
|---|---|
Bricks specific/brandBackground100 |
--color-brand-background-100 |
Typography/defaultHeading |
--color-default-heading |
Info state/infoBorder600 |
--color-info-border-600 |
Borders/nonInteractiveBorder |
--color-non-interactive-border |
Transparency/ghost0 |
--color-ghost-0 |
Spaces/lg |
--spacing-lg |
Radius/sm |
--radius-sm |
Conséquence pour le cron : le matching n'a pas besoin d'une table écrite à la main — une transformation de nom suffit, et tout ce qui ne matche pas par cette règle est un candidat drift. C'est le vrai livrable V0.
4.2 Drifts réels (code ↔ Figma)¶
| # | Drift | Figma | Code | Action |
|---|---|---|---|---|
| D7 | Poids de police, sur les 13 styles | Heading = Semi Bold · Text = Medium | Inter-Bold pour tous les Heading · Inter-Regular pour tous les Text |
Le plus impactant visuellement. Trancher qui fait foi, puis corriger d'un côté |
| D8 | Palier Shiny incohérent | Shiny/shinyBackground400 |
--color-shiny-background-500: #F9C25D |
Un des deux se trompe de palier |
| D9 | Palier absent côté code | Backgrounds/neutralBackground300 |
rampe = 50 / 100 / 200 / 400 | Ajouter le 300 côté code, ou le retirer de Figma s'il ne sert pas |
| D10 | Valeur différente d'un point | Borders/interactiveBorder = #dbd9d7 |
--color-interactive-border: #d8d9d7 |
Re-vérifier la valeur Figma (get_variable_defs) avant conclusion |
| D11 | Tokens code sans équivalent Figma relevé | — | --color-black (#13273e, doublon de defaultHeading), --color-black-deep, --color-modal-overlay, --color-none/transparent/current |
Vérifier : absents de Figma, ou hors périmètre design ? |
4.3 ⚠️ Correction de notre propre colonne Figma¶
Trois « valeurs de base connues » notées en juin sont en fait les background-500, pas les tokens texte :
| Token | Valeur notée ici | Valeur réelle côté code | Lecture |
|---|---|---|---|
successText |
#16b374 |
#08744d |
#16b374 = successBackground500 |
infoText |
#3280c2 |
#1d5187 |
#3280c2 = infoBackground500 |
pendingText |
#a66be1 |
#7b3ab6 |
#a66be1 = pendingBackground500 |
alertText |
#d72746 |
#d72746 |
✅ aligné |
Probable erreur de relevé de notre côté, pas un drift : à re-vérifier dans Figma avant de le remonter comme tel.
4.4 Alignés (nom + valeur vérifiés)¶
Espacements sm/lg/xl/3xl/4xl/8xl (8/12/16/24/32/64) · rayons sm/lg/full (8/16/9999) · defaultHeading #13273e · defaultText #76818b · appBackground #f9f5f1 · nonInteractiveBorder #eceae8 · white · ghost0→3 · les 3 disabled · les 10 tokens brand (dont brandBorder500, le renommage D1 est bien répercuté) · les rampes complètes success / alert / pending / info 50→950 · infoBorder600 et infoBorder950 (le code reproduit la structure atypique D2) · les 13 tailles de typo (Heading 3xs→3xl = 12→56 px, Text xs→lg = 10→16 px).
4.5 Score de sync V0¶
~85 tokens comparables · 5 drifts ouverts (D7→D11) · 1 erreur de relevé côté brain à corriger. D7 est structurel (poids de police sur tous les styles) ; D8/D9/D10 sont unitaires et actionnables ; D11 demande une vérification de périmètre.
5. D7 tranché — vérifié le 2026-08-18 (code + Storybook local)¶
Verdict : drift réel, mais uniquement sur le web. Le mobile est aligné.
Trois fichiers expliquent tout :
projects/common/front/theme/src/fonts.ts— les variables s'appellent biensemiboldetmedium(l'intention est donc celle de Figma), mais elles pointent vers des alias de police trompeurs :const semibold = 'Inter-Bold'etconst medium = 'Inter-Regular'. Aucun vrai Bold n'est utilisé nulle part.projects/common/uimmo/src/helpers/useThemeFonts.tsx— c'est là que l'alias est résolu, et il dépend de la plateforme :
| Alias | Mobile (native) | Web |
|---|---|---|
Inter-Bold (titres) |
Inter_600SemiBold ✅ |
Inter_500Medium 🎯 |
Inter-Regular (textes) |
Inter_500Medium ✅ |
Inter_400Regular 🎯 |
projects/storybook/.storybook/global.css— les@font-facedu web confirment :Inter-Bold=font-weight: 500,Inter-Regular=font-weight: 400, chargés depuisfonts.gstatic.com.
Mesure sur une story réelle (Accordion, Storybook local) : titre en famille Inter-Bold à 14 px / interligne 18,9 px / #13273e — conforme à heading/2xs sauf le poids, rendu en Medium 500 au lieu du SemiBold 600 de Figma. Le texte suit en Regular 400 au lieu de Medium 500.
Conclusion¶
- Mobile : conforme à Figma. Rien à faire.
- Web (Storybook,
front-app,app-pdp-financement) : tout le texte est rendu un cran plus léger que la maquette. Écart systémique, visible à l'œil sur les titres. - Question au lead dev avant de corriger : est-ce un choix assumé (rendu web souvent perçu plus gras à poids égal) ou un héritage non intentionnel ? La réponse détermine si on corrige le code ou si on documente la règle « web = un cran plus léger » côté design.
Deux pièges à retenir pour l'outillage¶
- Les alias de police mentent :
Inter-Boldne charge jamais de Bold. Un extracteur qui lit le nom de famille conclura faux. font-weightcalculé est inutilisable comme critère : il vaut400partout côté web, puisque le poids est porté par la famille (@font-face), pas par la propriété CSS. C'est exactement ce qui a produit le faux écart « fontWeight 400 vs 600 » du design QA de juin (BRI-301). La bonne clé de comparaison est le@font-face→ poids réel, pas le computed style.