Pular para conteúdo

0004 — Separadores escuros demais depois da spec 0019

Status CORRIGIDO
Branch fix/0004-separadores-escuros-demais
Aberto em 2026-08-05
Severidade MÉDIA
Apps afetados web (api · e2e sem impacto direto; o spec de contraste precisa acompanhar)

Status: RASCUNHO → DIAGNOSTICADO → EM CORREÇÃO → CORRIGIDO

1. Sintoma

Depois da spec 0019, as linhas ficaram escuras demais. O contorno dos painéis e as linhas entre itens de lista viraram o elemento mais forte da tela e competem com o conteúdo — a impressão é de "excesso de contraste", exatamente o defeito oposto ao que a 0019 foi corrigir.

Na lista de Análises de Crédito é onde mais aparece: vinte linhas de traço a 2,06:1 formam uma grade, e o painel em volta tem contorno de 3,52:1.

2. Reprodução

  1. Abrir /app/credit-analyses (ou qualquer lista) no tema claro.
  2. Observar o contorno do painel e as linhas entre as linhas da tabela.
  3. Abrir /app/renters/create e observar o contorno dos painéis de formulário.

  4. Ambiente: dev-remote, com o build da spec 0019 (merge cc4410f).

  5. Superfície: desktop e mobile, nos dois temas. Não é específico de breakpoint — é valor de token.
  6. Dados/pré-condições: nenhuma; qualquer papel com acesso à lista.

3. Esperado × Atual

  • Esperado: o separador delimita sem chamar atenção. A estrutura da tela vem de superfície e espaço; a linha é apoio, não protagonista.
  • Atual: contorno de painel a 3,52:1 e linha de lista a 2,06:1, no mesmo nível de peso visual que o texto de apoio.

4. Causa raiz

É regressão da spec 0019 — introduzida por mim, por aplicar a WCAG 1.4.11 larga demais.

O critério 1.4.11 (Non-text Contrast) exige 3:1 para "informação visual necessária para identificar componentes de interface e seus estados". A palavra que decide é identificar:

Elemento Identifica o componente? Régua correta
Borda de campo (input, select) Sim — sem ela não se sabe que ali se digita. É o exemplo canônico da norma. 3:1
Borda de painel / card Não — o painel é identificado pelo cabeçalho e pelo conteúdo decorativa
Linha entre itens de lista Não — separa leitura, não delimita componente decorativa

A spec 0019 tratou os três como o mesmo caso: divider e borderField receberam o mesmo #7B8A9E (RN1), e a única concessão foi o dividerSubtle a 2:1 (RN2) — que ainda é pesado para linha interna.

Agravante que a própria 0019 criou. A spec também passou a distinguir painel de fundo (branco contra #EDF1F6) e manteve o cabeçalho de painel tingido. Com isso a fronteira do painel passou a ser dita três vezes — superfície, cabeçalho e borda escura. Redundância em interface lê-se como ruído, e é o que faz o contorno parecer forte mesmo medindo "só" 3,5:1.

Onde está, em código:

  • apps/web/src/design-system/theme/palette.ts — divider e borderField com o mesmo valor nos dois temas; dividerSubtle a 2:1.
  • apps/web/src/design-system/theme/dataGrid.ts — .MuiDataGrid-cell usa dividerSubtle; cabeçalho e rodapé usam divider.
  • apps/web/src/design-system/theme/components.ts — MuiPaper e MuiCardHeader usam divider; MuiTableCell.head idem.

Por que a régua decorativa pode ser leve agora. Antes da 0019 o divisor a 1,20:1 era invisível porque não havia mais nada separando — painel e fundo diferiam 1,07:1 e não existia zebra perceptível. Hoje a superfície e a zebra fazem parte do trabalho, então o filete precisa de menos.

5. Correção

apps/api

Sem impacto.

apps/web

  • Onde: design-system/theme/palette.ts, theme/components.ts, theme/dataGrid.ts e os dois tokens/*.css.
  • O quê: separar o que hoje são dois níveis em três, um por função:
Nível Token Onde Claro Escuro Razão
Campo borderField input, select, textarea #8996AA #647387 3,0:1 — a norma exige
Painel divider card, diálogo, cabeçalho de tabela e de painel #ADB8C8 #49586C 2,0:1
Lista dividerSubtle linha entre itens #C9D4E0 #364559 1,5:1

O campo não muda de régua (só o hex, para bater 3,0 exato em vez de 3,52). O painel cai de 3,52 para 2,01. A linha de lista cai de 2,06 para 1,50 — ainda 25% acima do 1,20:1 que motivou a spec 0019, e agora apoiada pela zebra e pelo hover.

  • data-testid: nenhum novo.
  • Responsividade & PWA: valor de token, igual nos dois breakpoints. Sem impacto no service worker além do rebuild.

apps/e2e

  • Teste de regressão: color-contrast.spec.ts afere hoje ≥ 2,9 para a borda de painel e ≥ 1,8 e < 3,0 para a linha de lista. Esses limites codificam a regra errada e passam a exigir o inverso: painel na faixa decorativa, campo na estrutural. O spec passa a medir a borda de campo para o piso de 3:1 — que é o que a norma de fato pede — em vez da borda de painel.

6. Risco / impacto colateral

  • Não toca dinheiro — pricing, billing e sinistro não têm relação com cor.
  • O risco real é voltar ao problema original: separador invisível. Mitigado por manter a lista 25% acima do valor que gerou a queixa, e por aferir os três níveis no e2e.
  • docs/design-tokens.md e as RN1/RN2 da spec 0019 afirmam a regra antiga. Ficam errados se não forem corrigidos junto — e documentação errada é o que faz o token derivar de volta.

7. Critérios de aceite

  • [x] CA1. Seguindo os passos da seção 2, o contorno do painel e as linhas de lista não competem mais com o conteúdo.
  • [x] CA2. Borda de campo mede ≥ 3:1 contra o painel, nos dois temas — a única régua que a WCAG 1.4.11 de fato impõe aqui.
  • [x] CA3. Borda de painel mede entre 1,8:1 e 2,4:1; linha de lista entre 1,4:1 e 1,8:1, nos dois temas.
  • [x] CA4. Nenhum separador volta abaixo de 1,4:1 — o defeito que a spec 0019 corrigiu não retorna.
  • [x] CA5. color-contrast.spec.ts afere os três níveis e passa nos dois temas.
  • [x] CA6. docs/design-tokens.md e as RN1/RN2 da spec 0019 descrevem a regra nova, com a distinção "identifica componente × decora".
  • [x] CA7. tsc limpo, sem apontamento novo nos arquivos tocados.

8. Plano

  • [x] Reproduzir medindo os valores atuais no dev-remote (linha de base)
  • [x] apps/web — três níveis em palette.ts e nos dois tokens/*.css
  • [x] apps/web — components.ts e dataGrid.ts apontando cada uso ao nível certo
  • [x] apps/e2e — color-contrast.spec.ts medindo os três níveis
  • [x] docs/design-tokens.md + RN1/RN2 da spec 0019 com a regra corrigida
  • [x] make test e tsc sem apontamento novo
  • [x] /devremote-rebuild + medição nos dois temas e nos dois viewports

9. Decisões em aberto

Nenhuma. O usuário aprovou os três níveis da tabela da seção 5.

10. Registro

Antes × depois, medido no dev-remote

Antes (spec 0019) Depois Faixa alvo
Borda de campo — claro 3,52:1 3,00:1 ≥ 3,0
Borda de campo — escuro 3,07:1 3,03:1 ≥ 3,0
Painel / cabeçalho — claro 3,52:1 2,01:1 1,8–2,4
Painel / cabeçalho — escuro 3,07:1 2,02:1 1,8–2,4
Linha de lista — claro 2,06:1 1,50:1 1,4–1,8
Linha de lista — escuro 1,93:1 1,50:1 1,4–1,8

Os seis bateram na faixa nos dois temas, na primeira medição.

O que divergiu do plano

Nada nos valores. A divergência foi de escopo do teste: o color-contrast.spec.ts media a borda de painel para provar o piso de 3:1, o que era medir a coisa errada com o número certo. Passou a medir a borda de campo para esse piso, que é onde a WCAG 1.4.11 realmente se aplica, e a dar teto ao painel e à lista — antes só havia piso.

Isso é o que torna o teste capaz de pegar este defeito: separador que passa de filete a contorno é tão defeito quanto separador invisível, e um teste só com piso nunca acusaria.

O que fica dito na documentação

docs/design-tokens.md ganhou a tabela dos três níveis com o porquê de cada um, e as RN1/RN2 da spec 0019 receberam a nota de revisão apontando para este fix — a spec continua sendo o registro do que se decidiu na época, com o ajuste visível ao lado. Sem isso, alguém leria a RN1 daqui a três meses e devolveria o painel a 3:1.

Verificação

  • tsc: limpo.
  • color-contrast.spec.ts: 7/7 em chromium, nos dois temas, com os limites novos.
  • make test: não impactado — nenhum arquivo da API tocado (confirmado no diff).
  • Suíte e2e completa: 319 passaram, 6 pulados, zero falhas (17,6 min, chromium + firefox + webkit). Os 6 pulados são os semeadores em massa, já test.skip no repositório.