Pular para o conteúdo

Geração de Cores

A semente (só o tom main/400 de cada paleta) é o único valor que vem do Figma — o resto da escala (lighter…darker + os pares on-*) é calculado, não desenhado à mão. Compare a semente no Figma com o resultado gerado:

Use o gerador abaixo para explorar/testar escalas antes de propor uma cor nova — é a mesma implementação (scripts/tokens/generator.js) usada no build real, não uma simulação à parte.

tokens/
seeds/ # única coisa editada a mão
color.seeds.tokens.json # 1 hex por paleta (12 paletas), input do generator
spacing.tokens.json # valores fixos, grade de 8pt (docs/diretrizes-de-design-tokens.md 3.1)
radius.tokens.json # idem
font-size.tokens.json # idem
generated/ # nunca editado a mao
color.tokens.json # DTCG, output de resolve-color.js — consumido pelo Style Dictionary
color.legacy-resolved.tokens.json # output de build-tokens.js — consumido só pelo splice em _light.scss
dist/ # output do Style Dictionary (build de teste, ver secao abaixo)
Figma (só sementes) — semi-manual, ver "Sync com Figma"
↓
tokens/seeds/color.seeds.tokens.json — DTCG, 1 hex por paleta
↓
scripts/tokens/generator.js — puro: escala 50..900 + on-colors (APCA)
↓
├─► scripts/tokens/build-tokens.js → tokens/generated/color.legacy-resolved.tokens.json
│ → região marcada de src/scss/themes/_light.scss (mecanismo de PRODUÇÃO hoje)
│
└─► scripts/tokens/resolve-color.js → tokens/generated/color.tokens.json (DTCG)
→ style-dictionary.config.js → tokens/dist/tokens.css (build de TESTE, paralelo)

Hoje existem dois caminhos de saída porque o Style Dictionary ainda não substituiu o mecanismo de produção — ver “Style Dictionary (build de teste)” abaixo pra entender por quê e o que falta pra unificar.

src/stories/foundations/TokenManager.stories.ts (Storybook, “Foundations/Gerenciador de Tokens”) importa as mesmas funções puras de scripts/tokens/generator.js — a lógica de geração de escala e contraste não está mais duplicada entre a story e o build.

  1. Edite tokens/seeds/color.seeds.tokens.json (não edite _light.scss diretamente — a região entre /* @mds-tokens:generated:start */ e /* @mds-tokens:generated:end */ é sobrescrita a cada build).
  2. Rode npm run tokens.
  3. Revise o diff de src/scss/themes/_light.scss e tokens/generated/color.legacy-resolved.tokens.json antes de commitar.
  4. npm run tokens:verify roda em CI (modo --check) e falha se alguém esquecer de rodar o passo 2.

O Figma (“Design System 2.0”) é a fonte de verdade das cores-semente, mas a sincronização ainda não é automatizada via API — é feita rodando Claude com as ferramentas MCP do Figma:

  1. Abrir o arquivo Figma e localizar as variáveis de semente (_Brand-*, _Blue, _Aqua, etc. na coleção _Primitives / Colors).
  2. Rodar get_variable_defs nessas variáveis via Claude.
  3. Atualizar os hex correspondentes em tokens/seeds/color.seeds.tokens.json.
  4. Rodar npm run tokens e revisar o diff.

brand-varejo foi removido do conjunto de paletas (2026-09-22, decisão de design — não existe mais).

Duas regiões marcadas em _light.scss, ambas mecânicas a partir de palettes.config.js:

  1. @mds-tokens:generated — a camada de paletas (--mds-colors-palettes-<prefixo>-*, incluindo gray) e os aliases semânticos (--mds-colors-primary-*, -secondary-*, -danger-*, -warning-*, -info-*, -success-*), só var() apontando pra paleta certa.
  2. @mds-tokens:generated-themes — os blocos &[data-primary="<prefixo>"] (“modelo de tema”: troca qual paleta vira --mds-colors-primary-* via atributo), um por paleta com selectableAsPrimary: true em palettes.config.js. Adicionado em 2026-09-22 — antes desses blocos serem gerados, eles removiam/comentavam de forma inconsistente uma linha --mds-colors-ui-primary (quebrada em 9 dos 10 blocos, referenciando uma variável inexistente; ver histórico do arquivo). Verificado que essa linha não tinha efeito real (comentada ou apontando pra var inexistente) antes de deixar de gerá-la — 130 das 140 declarações de tema batem exatamente contra o CSS compilado da produção anterior; as 10 que somem são exatamente essa linha morta.

O resto de _light.scss (buttons-*, menu-*, control-*, highlight-*, item-*, ui-*, background-*, foreground-*) continua curado à mão — são decisões de design sobre qual papel semântico usar em qual estado, não cor calculável. _dark.scss está fora de escopo por enquanto (dark mode é uma iniciativa separada, ainda não retomada).

Reverso-engenhado em 2026-09-22 a partir dos valores de produção — não é o mesmo algoritmo que TokenManager.stories.ts usava até então (selectOnColor, que buscava o melhor contraste dentro da própria escala 50..900). O valor real de produção segue um padrão diferente:

  • cada paleta tem exatamente 2 candidatos: branco e preto, cada um misturado com ~3% do matiz da própria semente (computeOnCandidates em generator.js) — pra o texto nunca ficar num branco/preto sem matiz;
  • para cada step, escolhe-se o candidato com maior contraste APCA em magnitude absoluta (pickOnColor).

Essa combinação reproduz 344 das 350 variáveis geradas byte-a-byte contra a produção atual (sobre as 12 paletas restantes, sem brand-varejo). As 6 exceções conhecidas:

Variável Produção Gerado Motivo
brand-mobiis-on-light / on-lighter valor único tint/shade padrão drift manual já documentado no DESIGN.md (patch do primary-light)
brand-log-light (+ seu on-) usa step 300 (tint 25%) usa step 200 (tint 50%, padrão) essa paleta parece usar um mapeamento de step diferente das outras — não normalizado ainda, ver STEP_MAP em palettes.config.js
aqua-on-dark, brand-on-light prefere preto prefere branco empate técnico (diferença de ~2-4 Lc no APCA); WCAG concorda com a produção nesses 2 casos mas erra em ~6 outros (subpondera azul), então não foi adotado como critério geral
brand-mobiis-dark #3068bc #3068bb arredondamento de 1 unidade de hex, irrelevante

Nenhuma dessas foi “corrigida” à força — optei por manter a fórmula consistente entre as 13 paletas em vez de replicar a exceção; se alguma dessas 8 for intencional (não um erro antigo), ela deveria ser resolvida no Figma (semente ou step diferente), não hardcoded de volta no SCSS.

Rodar npm run tokens:sd gera tokens/dist/tokens.css a partir de: tokens/generated/color.tokens.json (DTCG, saída de resolve-color.js) + tokens/seeds/{spacing,radius,font-size}.tokens.json (valores estáticos, sem generator — vêm direto da seção 3.1 do documento de diretrizes).

Validado byte-a-byte contra produção: as 216 custom properties que o Style Dictionary gera (cor + spacing + radius + font-size) batem exatamente com o CSS compilado real (_light.scss, _spacing.scss, _radius.scss, _typography.scss) — sem nenhum transform ou format customizado, só estruturando o JSON como { "mds": { "<categoria>": {...} } } pra a transform css nativa (transformGroup: 'css', kebab-case) já produzir o nome certo (--mds-colors-palettes-brand-main, --mds-spacing-md…).

Por que ainda é um build paralelo, não o mecanismo de produção: tokens/dist/tokens.css é um arquivo novo — trocar o mecanismo de produção por ele significa os consumidores do pacote publicado passarem a importar um arquivo a mais (hoje o splice na região marcada de _light.scss não muda o contrato de arquivos publicados). Essa é uma decisão consciente de fazer depois, não um efeito colateral silencioso.

O que falta pra virar produção:

  1. Decidir o contrato de arquivo (gerar dentro de _light.scss via um format customizado que produz só o texto, mantendo o splice; ou aceitar o arquivo novo e atualizar quem consome o pacote).
  2. Consolidar a resolução de cor duplicada hoje entre build-tokens.js (splice) e resolve-color.js (DTCG) — as duas chamam generator.js/palettes.config.js, só formatam a saída diferente.
  3. Adicionar uma platform js/ts pro tema do projeto React + MUI (o motivo original de trazer o Style Dictionary pra esse projeto).
  4. Trazer spacing/radius/font-size pra dentro do arquivo real (_spacing.scss etc. continuam hand-authored hoje — só o build de teste os replica, eles não são gerados de fato ainda).
  • Fechar os pontos acima pra promover o Style Dictionary de “build de teste” pra mecanismo de produção.
  • Automatizar a sync com Figma via REST API, se o processo semi-manual virar gargalo.
  • Decidir e normalizar as exceções documentadas na seção anterior com o time de design.
  • Puxar os valores reais de elevação/blur do Figma (ver documento de diretrizes, seção 3.2) antes de trazer essas duas categorias pro pipeline.