ADR-026 ActifActive contract

Figma synchronization strategy for custom brand palettes

DateDate
2026-05-29
DécideursDecision makers
Guilherme Negreiros — Design System Lead, Principal Designer

Context

ADR-024 introduced two custom brand palettes (rose-coral accent and bordeaux secondary) into tokens/primitives.json. Unlike the Radix UI palettes already present (Teal, Blue, Red, etc.), these palettes:

1. Are not on Figma Community — Tokens Studio cannot import them from an official shared file 2. Have no external reference documentation — users must understand each step from the JSON alone 3. Can evolve — the hex values are design decisions, not constants inherited from a third-party system

The question raised in ADR-024's debt log:

How are custom palettes synchronized with Figma reliably, in a governed way, without creating a second source of truth?


Decision

Principle: the same pipeline as the Radix palettes

The custom palettes (accent, secondary) are handled exactly like the Radix palettes in the sync pipeline. There is no special process for them.

tokens/primitives.json
  ↓ (Tokens Studio reads this file)
Figma Variables — "Primitives" collection
  ↓ (designers use it via semantic tokens)
Figma Variables — "Semantic" + "Component" collections

Tokens Studio makes no distinction between a Radix palette and a custom palette — it reads the JSON and maps tokens to Figma Variables based on the file's structure.


Tokens Studio configuration

Target Figma collection: Primitives (the same collection as primitive.color.teal, primitive.color.blue, etc.)

Automatic naming in Figma:

  • primitive/color/accent/1 → Figma variable accent/1
  • primitive/color/accent/9 → Figma variable accent/9
  • primitive/color/secondary/9 → Figma variable secondary/9
  • etc.

_readme tokens (type other) are ignored by Tokens Studio on import — they do not generate Figma variables. They exist solely to document the JSON for agents and developers.

Import order (unchanged since ADR-011): 1. primitives.jsonPrimitives collection 2. semantic.jsonSemantic collection 3. component.jsonComponent collection


When custom values change

Any modification of a custom palette's hex values follows the standard process:

1. Open a token(primitives) PR on a token/brand-palette-update branch 2. Modify the values in tokens/primitives.json 3. Mandatory approval from the Principal Designer (governance rule ADR-001, ADR-004) 4. Merge → the Tokens Studio sync pipeline detects the change on the next pull from Figma

Designers do not modify values directly in Figma. If a hue doesn't work, they open an issue / submit a PR — not a local Figma variable edit.


Documenting steps in Figma

Figma variable descriptions (the description field in Tokens Studio) are populated from each JSON token's $description field. Designers see directly in the Figma panel:

Figma variableAutomatic description
accent/9Solid background — brand accent / secondary CTA
accent/11Accent text — 7.1:1 on white (WCAG AA+AAA)
secondary/9Solid dark background — 12.2:1 with white text
secondary/12High-contrast text — 13.8:1 on white (WCAG AAA)

The per-step usage rule (inherited from the Radix convention — steps 1-2 backgrounds, 9-10 solids, 11-12 text) applies to the custom palettes as well. It is documented in the _readme field of each palette in primitives.json.


Validation after sync

After each custom palette update in Figma, the Principal Designer validates:

  • [ ] All 12 steps of each palette appear in the Primitives collection
  • [ ] The semantic/color/brand/* semantic tokens correctly resolve their aliases
  • [ ] No orphaned Figma variable (broken alias) in the Semantic or Component collections
  • [ ] Variable descriptions match the JSON's $description values

What an agent may do

✅ Modify hex values in tokens/primitives.json via PR
✅ Add a new intermediate step (e.g. accent/9-5) if justified
✅ Update the $description fields to improve Figma documentation
❌ Modify Figma variables directly (never — the direction is JSON → Figma)
❌ Create a new palette without an ADR and Principal Designer approval

Rationale

Why not create a separate Figma collection for the custom palettes?

A Brand collection separate from Primitives:

  • Introduces an asymmetry between the Figma structure and the JSON structure (where everything lives in primitives.json)
  • Complicates the Tokens Studio import rules (order, alias resolution)
  • Provides no benefit to agents — who work on the JSON, not on Figma

Keeping everything in the Primitives collection preserves consistency between JSON and Figma.

Why don't _readme entries create Figma variables?

Tokens Studio ignores tokens of type other when importing variables (they are not design values — no usable $value). This behavior is documented and intentional. _readme entries are a documentation pattern internal to the JSON.


Rejected alternatives

AlternativeReason for rejection
Create the custom palettes manually in FigmaCreates a second source of truth outside the repo. Drift is guaranteed at the next update.
Host the custom palettes in a separate JSON fileFragments primitives.json with no benefit — Tokens Studio can manage a single file for all primitives.
Use Figma Styles (not Variables)Figma Styles do not support aliases/references — semantic tokens could not point to the primitives. Figma Variables is the right mechanism.
Wait for a Radix forkThe custom colors do not correspond to any existing Radix palette. Waiting for a hypothetical similar Radix palette is not actionable.

Consequences

Immediate:

  • The accent and secondary palettes are available in Figma on the next Tokens Studio pull from the repo
  • No additional configuration required — they appear automatically in the Primitives collection

For designers:

  • Same workflow as for Radix palettes — nothing new to learn
  • Step descriptions are visible directly in the Figma Variables panel
  • Any request to change a hue goes through a PR, not a local Figma edit

For AI agents:

  • Agents continue to work exclusively on the JSON files
  • Figma sync is transparent to agents — it does not change token usage rules

For governance:

  • A custom palette with no ADR = drift — audit-tokens.js can detect tokens with no associated documentation
  • Any new custom palette triggers the creation of an ADR + Principal Designer approval

Debt resolved:

  • The debt documented in ADR-024 ("a separate ADR must document the Figma sync strategy for custom palettes") is resolved by this ADR.

Contexte

ADR-024 a introduit deux palettes de marque custom (accent rose-corail et secondary bordeaux) dans tokens/primitives.json. Contrairement aux palettes Radix UI déjà présentes (Teal, Blue, Red, etc.), ces palettes :

1. Ne sont pas dans Figma Community — Tokens Studio ne peut pas les importer depuis un fichier partagé officiel 2. N'ont pas de documentation de référence externe — les utilisateurs doivent comprendre chaque step depuis le JSON seul 3. Peuvent évoluer — les valeurs hex sont décisions de design, pas des constantes issues d'un système tiers

La question soulevée dans la dette d'ADR-024 :

Comment les palettes custom sont-elles synchronisées avec Figma de manière fiable, gouvernée, et sans créer une seconde source de vérité ?


Décision

Principe : même pipeline que les palettes Radix

Les palettes custom (accent, secondary) sont traitées exactement comme les palettes Radix dans le pipeline de sync. Il n'existe pas de processus spécial pour elles.

tokens/primitives.json
  ↓ (Tokens Studio lit ce fichier)
Variables Figma — Collection "Primitives"
  ↓ (les designers utilisent via semantic tokens)
Variables Figma — Collection "Semantic" + "Component"

Tokens Studio ne fait pas de distinction entre une palette Radix et une palette custom — il lit le JSON et mappe les tokens à des Variables Figma selon la structure du fichier.


Configuration Tokens Studio

Collection Figma cible : Primitives (même collection que primitive.color.teal, primitive.color.blue, etc.)

Nommage automatique dans Figma :

  • primitive/color/accent/1 → variable Figma accent/1
  • primitive/color/accent/9 → variable Figma accent/9
  • primitive/color/secondary/9 → variable Figma secondary/9
  • etc.

Les tokens _readme (type other) sont ignorés par Tokens Studio à l'import — ils ne génèrent pas de variables Figma. Ils servent exclusivement à la documentation du JSON pour les agents et développeurs.

Import order (inchangé depuis ADR-011) : 1. primitives.json → Collection Primitives 2. semantic.json → Collection Semantic 3. component.json → Collection Component


Quand les valeurs custom changent

Toute modification des valeurs hex d'une palette custom suit le processus standard :

1. Ouvrir une PR de type token(primitives) sur une branche token/brand-palette-update 2. Modifier les valeurs dans tokens/primitives.json 3. Approbation obligatoire du Principal Designer (règle gouvernance ADR-001, ADR-004) 4. Merge → le pipeline de sync Tokens Studio détecte le changement au prochain pull depuis Figma

Les designers ne modifient pas les valeurs directement dans Figma. Si une teinte ne convient pas, ils ouvrent une issue / soumettent une PR — pas une modification locale de variable Figma.


Documentation des steps dans Figma

Les descriptions des variables Figma (champ description dans Tokens Studio) sont renseignées depuis le champ $description de chaque token JSON. Les designers voient directement dans le panneau Figma :

Variable FigmaDescription automatique
accent/9Solid background — brand accent / CTA secondaire
accent/11Texte accent — 7.1:1 sur blanc (WCAG AA+AAA)
secondary/9Solid dark background — 12.2:1 avec texte blanc
secondary/12High-contrast text — 13.8:1 sur blanc (WCAG AAA)

La règle d'usage par step (héritée de la convention Radix — steps 1-2 fonds, 9-10 solides, 11-12 texte) s'applique aux palettes custom. Elle est documentée dans le champ _readme de chaque palette dans primitives.json.


Validation après sync

Après chaque mise à jour de palette custom dans Figma, le Principal Designer valide :

  • [ ] Les 12 steps de chaque palette apparaissent dans la collection Primitives
  • [ ] Les tokens sémantiques semantic/color/brand/* résolvent correctement les alias
  • [ ] Aucune variable Figma orpheline (alias cassé) dans les collections Semantic ou Component
  • [ ] Les descriptions de variables correspondent aux $description du JSON

Ce qu'un agent peut faire

✅ Modifier les valeurs hex dans tokens/primitives.json via PR
✅ Ajouter un nouveau step intermédiaire (ex: accent/9-5) si justifié
✅ Mettre à jour les $description pour améliorer la documentation Figma
❌ Modifier les variables Figma directement (jamais — direction JSON → Figma)
❌ Créer une nouvelle palette sans ADR et sans approbation Principal Designer

Argumentaire

Pourquoi ne pas créer une collection Figma séparée pour les palettes custom ?

Une collection Brand séparée des Primitives :

  • Introduit une asymétrie dans la structure Figma vs la structure JSON (où tout est dans primitives.json)
  • Complique les règles d'import Tokens Studio (ordre, résolution des alias)
  • Ne bénéficie pas aux agents — qui travaillent sur le JSON, pas sur Figma

Garder tout dans la collection Primitives préserve la cohérence entre JSON et Figma.

Pourquoi les _readme ne créent-ils pas de variables Figma ?

Tokens Studio ignore les tokens de type other à l'import des variables (ils ne sont pas des valeurs de design — pas de $value utile). Ce comportement est documenté et intentionnel. Les _readme sont un pattern de documentation interne au JSON.


Alternatives rejetées

AlternativeRaison du rejet
Créer les palettes custom manuellement dans FigmaCrée une seconde source de vérité hors du repo. Dérive garantie à la prochaine mise à jour.
Héberger les palettes custom dans un fichier JSON séparéFragmente primitives.json sans bénéfice — Tokens Studio peut gérer un seul fichier pour tous les primitifs.
Utiliser des Figma Styles (pas des Variables)Les Figma Styles ne supportent pas les alias/références — les tokens sémantiques ne pourraient pas pointer vers les primitifs. Variables Figma est le bon mécanisme.
Attendre un fork RadixLes couleurs custom ne correspondent à aucune palette Radix existante. Attendre une hypothétique palette Radix similaire n'est pas actionnable.

Conséquences

Immédiates :

  • Les palettes accent et secondary sont disponibles dans Figma au prochain pull Tokens Studio depuis le repo
  • Aucune configuration supplémentaire requise — elles apparaissent automatiquement dans la collection Primitives

Pour les designers :

  • Même workflow que pour les palettes Radix — rien à apprendre de nouveau
  • Les descriptions de step sont visibles directement dans le panneau Variables Figma
  • Toute demande de modification de teinte passe par une PR, pas par une modification Figma locale

Pour les agents IA :

  • Les agents continuent de travailler exclusivement sur les fichiers JSON
  • La sync Figma est transparente pour les agents — elle ne change pas les règles d'usage des tokens

Pour la gouvernance :

  • Une palette custom sans ADR = dérive — l'audit-tokens.js peut détecter des tokens sans documentation associée
  • Toute nouvelle palette custom déclenche la création d'un ADR + approbation Principal Designer

Dette soldée :

  • La dette documentée dans ADR-024 ("un ADR séparé devra documenter la stratégie de sync Figma pour les palettes custom") est soldée par cet ADR.
← ADR-025 ADR-027 →