5.0 KiB
UI Troubleshooting & Resolução de Estilos (JavaFX CSS)
Este documento registra a investigação da causa raiz de problemas visuais na interface gráfica do CyberCore Signer, em especial a falha de renderização de textos escuros sobre fundo escuro no tema escuro.
1. O Problema: Texto Preto sobre Fundo Escuro (Contraste ~1.1:1)
Sintoma
No tema escuro (ThemeManager.AppTheme.DARK / .theme-dark), determinados textos nos diálogos ExitConfirmationDialog (texto explicativo da ação), PdfSignDialog (nome e metadados do documento PDF selecionado, dica de arraste do selo visual) e PdfCertificateSignDialog (opção de memorização segura de PIN) eram renderizados com a cor preta (#000000) sobre um fundo escuro (#090d16 ou #111827).
O contraste medido entre o texto e o fundo situava-se em aproximadamente 1.1:1 a 1.2:1, violando completamente as diretrizes de acessibilidade WCAG AA (mínimo de 4.5:1 para texto normal) e tornando o texto praticamente invisível.
2. Investigação Técnica e Causa Raiz
2.1 Lookups Inexistentes no CSS
Ao inspecionar o código-fonte Java dessas telas, verificou-se o uso de estilos inline via setStyle(...):
subtitle.setStyle("-fx-text-fill: -fx-text-secondary; -fx-font-size: 12px;");
lblDocName.setStyle("-fx-font-weight: bold; -fx-font-size: 12.5px; -fx-text-fill: -fx-text-primary;");
lblDocMeta.setStyle("-fx-font-size: 11px; -fx-text-fill: -fx-text-secondary;");
previewBox.setStyle("-fx-background-color: -fx-bg-primary; -fx-border-color: -fx-border-light; ...");
chkRememberPin.setStyle("-fx-font-size: 11.5px; -fx-text-fill: -fx-text-primary;");
Os tokens -fx-text-primary, -fx-text-secondary, -fx-bg-primary, -fx-border-light e -fx-accent não estavam declarados no arquivo de folha de estilos theme.css.
2.2 Por que o JavaFX rebaixa para preto (#000000)?
No motor de estilização do JavaFX (com.sun.javafx.css / Modena):
- Quando uma declaração inline em
setStyle(...)utiliza uma cor de lookup (-fx-text-fill: <variavel>), o analisador CSS do JavaFX tenta resolver essa variável percorrendo os ancestrais do nó até o.rootda cena. - Caso a variável não seja encontrada, o
StyleConverterdo JavaFX não lança exceção em tempo de execução. Em vez disso, seu mecanismo de tolerância a falhas adota o valor fallback padrão da especificação base de controles:Color.BLACK(rgba(0, 0, 0, 1.0)). - Em um tema claro, o fundo é branco ou cinza claro (
#ffffff/#f1f5f9), de modo que o texto preto parece ter funcionado por pura coincidência de luminância. - No tema escuro, no entanto, o fundo da aplicação é escuro (
#090d16a#111827), fazendo com que o fallback para#000000destrua o contraste da interface.
2.3 Problemas Adicionais com setStyle(...)
- Prioridade Forçada:
setStyle(...)tem especificidade de estilo inline (prioridade máxima), sobrescrevendo quaisquer regras de temas.theme-lighte.theme-darkque tentem ajustar o elemento. - Acoplamento: Espalha lógica visual e regras de cor pelo código Java, dificultando testes de regressão automatizados e auditorias de contraste.
3. Diretrizes e Solução Adotada
3.1 Definição Completa de Tokens e Aliases no theme.css
Todos os tokens semânticos e seus aliases de compatibilidade são declarados formalmente nos blocos canônicos de tokens:
.theme-light {
-fx-text-primary: -fx-color-text;
-fx-text-secondary: -fx-color-text-muted;
-fx-bg-primary: -fx-color-surface;
-fx-border-light: -fx-color-border-subtle;
-fx-accent: -fx-color-primary;
}
.theme-dark {
-fx-text-primary: -fx-color-text;
-fx-text-secondary: -fx-color-text-muted;
-fx-bg-primary: -fx-color-surface;
-fx-border-light: -fx-color-border;
-fx-accent: -fx-color-primary;
}
3.2 Eliminação de Cores Inline
É terminantemente proibido utilizar setStyle(...) com propriedades que afetem cores:
- Proibidos em
setStyle:-fx-text-fill,-fx-background-color,-fx-border-color,-fx-fill,-fx-strokeou códigos#hex. - Permitidos em
setStyleexclusivamente quando estritamente necessário: geometria e layout (-fx-min-width,-fx-pref-width,-fx-padding).
Toda estilização cromática deve ser feita atribuindo classes semânticas:
.text-primary: Texto principal com alta luminância no escuro e baixa no claro..text-secondary,.text-muted: Texto secundário / auxiliar com contraste garantido >= 4.5:1..text-accent: Destaque com a cor primária da marca..surface-box,.toolbar-box: Caixas de superfície neutra e barras de ferramentas.
3.3 Testes Automatizados de Guarda-Corpo
O projeto mantém testes unitários automatizados em DesignTokenGuardrailTest e CssColorAndContrastGuardrailTest que:
- Fazem varredura estática de todo o código Java da UI para reprovar qualquer
setStyleque declare cor ou hexadecimal. - Validam matematicamente a fórmula de luminância relativa WCAG 2.1 para cada par texto/fundo nos dois temas, garantindo conformidade rigorosa.