feat: enhance accessibility and theme consistency in components
This commit is contained in:
1 parent
a279269f8f
commit
3de4f2501d
3 files changed
+170
-26
No files matched your search
@@ -9,7 +9,12 @@
|
||||
* 2. PAR INVERTIDO: no tema escuro o texto deveria clarear (número menor)
|
||||
* e o fundo/borda deveria escurecer (número maior).
|
||||
* 3. CONTRASTE BAIXO: par abaixo de 4.5:1 (AA para texto).
|
||||
* 4. COR FIXA INLINE: style={{ borderColor: 'rgba(...)' }} com valor literal.
|
||||
* 4. SEM TEMA ESCURO: arquivo que pinta cor mas não tem nenhuma variante
|
||||
* dark:. Foi assim que o glossário passou meses só com
|
||||
* tema claro sem ninguém notar.
|
||||
* 5. FAMÍLIA FORA DO PADRÃO: gray/zinc/neutral/stone no lugar de slate. Além
|
||||
* de destoar, escapa das checagens acima, que olham slate.
|
||||
* 6. COR FIXA INLINE: style={{ borderColor: 'rgba(...)' }} com valor literal.
|
||||
* Style inline vence classe, então anula a cor do tema
|
||||
* (inclusive as variantes dark: e hover:). Cor vinda do
|
||||
* dado (serie.cor) é permitida, ver DESIGN.md seção 5.
|
||||
@@ -79,6 +84,13 @@ const RX_TEXTO_INVERTIDO = /\btext-white dark:text-slate-(?:[5-9]\d0|950)\b/;
|
||||
const RX_BLOCO_STYLE = /style=\{\{([\s\S]*?)\}\}/g;
|
||||
// Cor literal: aspas seguidas de #, rgb(), hsl() ou nome de cor.
|
||||
const RX_COR_FIXA = /\b(borderColor|backgroundColor|color)\s*:\s*['"](?:#|rgb|hsl|transparent|white|black)/g;
|
||||
// Qualquer classe que pinte cor, para medir se o arquivo tem tema escuro.
|
||||
const RX_PINTA = /\b(?:text|bg|border|divide|from|via|to)-(?:slate|gray|zinc|neutral|stone|white)(?:-\d+)?(?:\/\d+)?\b/g;
|
||||
// Famílias de cinza fora do padrão do projeto (que é slate).
|
||||
const RX_FAMILIA_ERRADA = /\b(?:text|bg|border|divide|from|via|to)-(gray|zinc|neutral|stone)-\d+/g;
|
||||
// Variante dark: DE VERDADE, seguida de um utilitário. Procurar só por "dark:"
|
||||
// daria falso negativo: a palavra aparece em comentário e em texto visível.
|
||||
const RX_VARIANTE_DARK = /\bdark:(?:hover:|focus:|group-hover:|active:)?[a-z]+-/;
|
||||
|
||||
/** Cor literal dentro de style={{}}: vence a classe e mata a variante dark:. */
|
||||
function coresFixasInline(arq) {
|
||||
@@ -99,11 +111,26 @@ function main() {
|
||||
const invertidos = [];
|
||||
const fracos = [];
|
||||
const fixas = [];
|
||||
const semTemaEscuro = [];
|
||||
const familiaErrada = new Map();
|
||||
|
||||
for (const arq of arquivos()) {
|
||||
fixas.push(...coresFixasInline(arq));
|
||||
|
||||
const linhas = readFileSync(arq, "utf8").split("\n");
|
||||
const bruto = readFileSync(arq, "utf8");
|
||||
// Um arquivo que pinta muita cor e não tem nenhuma variante dark: quase
|
||||
// certamente não acompanha o tema.
|
||||
const pinta = (bruto.match(RX_PINTA) || []).length;
|
||||
const temDark = RX_VARIANTE_DARK.test(bruto);
|
||||
if (pinta >= 8 && !temDark) {
|
||||
semTemaEscuro.push([arq, `${pinta} classes de cor, nenhuma variante dark:`]);
|
||||
}
|
||||
for (const m of bruto.matchAll(RX_FAMILIA_ERRADA)) {
|
||||
const chave = `${arq} ${m[1]}-*`;
|
||||
familiaErrada.set(chave, (familiaErrada.get(chave) ?? 0) + 1);
|
||||
}
|
||||
|
||||
const linhas = bruto.split("\n");
|
||||
linhas.forEach((linha, i) => {
|
||||
const n = i + 1;
|
||||
|
||||
@@ -163,13 +190,25 @@ function main() {
|
||||
}
|
||||
}
|
||||
|
||||
secao("ARQUIVOS SEM TEMA ESCURO", semTemaEscuro);
|
||||
|
||||
if (familiaErrada.size) {
|
||||
const total = [...familiaErrada.values()].reduce((a, b) => a + b, 0);
|
||||
console.log(`\nFAMÍLIA DE CINZA FORA DO PADRÃO: ${total}`);
|
||||
console.log(" (o projeto usa slate; gray/zinc/neutral/stone destoam e escapam da auditoria)");
|
||||
for (const [k, v] of [...familiaErrada].sort((a, b) => b[1] - a[1])) {
|
||||
console.log(` ${v}x ${k}`);
|
||||
}
|
||||
}
|
||||
|
||||
secao("PARES INVERTIDOS", invertidos);
|
||||
secao(`PARES ABAIXO DE AA (${AA}:1)`, fracos);
|
||||
secao("COR FIXA EM STYLE INLINE", fixas);
|
||||
|
||||
const total =
|
||||
[...inexistentes.values()].reduce((a, b) => a + b, 0) +
|
||||
invertidos.length + fracos.length + fixas.length;
|
||||
[...familiaErrada.values()].reduce((a, b) => a + b, 0) +
|
||||
invertidos.length + fracos.length + fixas.length + semTemaEscuro.length;
|
||||
console.log(`\n${total === 0 ? "OK, nenhum problema." : `${total} problema(s).`}`);
|
||||
console.log("Exceção legítima: painel escuro nos DOIS temas (tooltip, bloco de código).");
|
||||
console.log("Nesses casos não use variante dark:. Ver DESIGN.md seção 4.");
|
||||
|
||||
Reference in new issue
Block a user