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¶
- Abrir
/app/credit-analyses(ou qualquer lista) no tema claro. - Observar o contorno do painel e as linhas entre as linhas da tabela.
-
Abrir
/app/renters/createe observar o contorno dos painéis de formulário. -
Ambiente: dev-remote, com o build da spec 0019 (merge
cc4410f). - Superfície: desktop e mobile, nos dois temas. Não é específico de breakpoint — é valor de token.
- 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—dividereborderFieldcom o mesmo valor nos dois temas;dividerSubtlea 2:1.apps/web/src/design-system/theme/dataGrid.ts—.MuiDataGrid-cellusadividerSubtle; cabeçalho e rodapé usamdivider.apps/web/src/design-system/theme/components.ts—MuiPapereMuiCardHeaderusamdivider;MuiTableCell.headidem.
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.tse os doistokens/*.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.tsafere hoje≥ 2,9para a borda de painel e≥ 1,8 e < 3,0para 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.mde 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.tsafere os três níveis e passa nos dois temas. - [x] CA6.
docs/design-tokens.mde as RN1/RN2 da spec 0019 descrevem a regra nova, com a distinção "identifica componente × decora". - [x] CA7.
tsclimpo, 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 empalette.tse nos doistokens/*.css - [x]
apps/web—components.tsedataGrid.tsapontando cada uso ao nível certo - [x]
apps/e2e—color-contrast.spec.tsmedindo os três níveis - [x]
docs/design-tokens.md+ RN1/RN2 da spec 0019 com a regra corrigida - [x]
make testetscsem 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.skipno repositório.