Diagnóstico · 5 lentes de UX sênior · de-para

Onde o DS está hoje,
e como vira o melhor do Brasil.

Cinco analistas sênior varreram o DS e as telas — heurísticas de Nielsen, benchmark dos melhores DS do mundo, acessibilidade WCAG, microinterações e densidade de dados. Cada achado virou um de-para hoje→ideal; uma parte já foi aplicada nesta rodada, o resto está priorizado pra V2.

68→
maturidade heurística
subindo nesta rodada
2 de 3
tier vs. mercado
"consolidando"
4
pares de contraste corrigidos
AA garantido
21
microinterações
catalogadas + defendidas
Heurísticas (Nielsen + leis de UX)Benchmark (Polaris · Material · Carbon · Linear…)Acessibilidade WCAG 2.1 AAMicrointeraçõesDensidade comex
Achados → Ideal

De-para componente a componente

18 achados na avaliação heurística. Os de maior severidade já entraram nesta rodada; o resto está priorizado.

ÁreaHojeIdealStatus
Tabela — estado de loading
severidade 3
Sem skeleton: em rede real, tela vazia ou flash de conteúdo.Prop loading → linhas-esqueleto que preservam colunas/altura. Aplicado
Tabela — estado vazio
severidade 3
rows=[] renderiza tbody vazio; cada tela improvisava o vazio.emptyState nativo (P2Empty) dentro do frame quando 0 linhas. Aplicado
Ordenação falsa
severidade 2
Ícone "sortable" era decorativo — não ordenava (engana o usuário).Ordenação real asc/desc + aria-sort no header. Aplicado
A11y de controles
severidade 2
Checkbox/switch/seleção eram <span onClick> sem role nem teclado.role + aria-checked/pressed + foco + operação por teclado. Aplicado
Feedback de ação
severidade 3
Conferir/Classificar mudavam estado em silêncio, sem confirmação.P2Toast de sucesso/erro (com "Desfazer" no reversível). Aplicado
Movimento
severidade 2
Sem prefers-reduced-motion; só 2 keyframes, sem tokens de motion.Escala de duração/easing + reduced-motion global. Aplicado
Confirmação destrutiva
severidade 3
"Devolver"/lote disparam direto, sem confirmar.P2ConfirmDialog obrigatório p/ danger/irreversível.V2
Drawer acessível
severidade 2
Sem Esc, foco-trap nem lock de scroll.Radix Dialog: Esc, foco-trap, aria-modal, restaura foco.V2
Paginação
severidade 2
Footer diz "12 de 128" mas não há como ver além.P2Pagination / "carregar mais" plugado no footer.V2
Estado de erro
severidade 3
Sem P2ErrorState; input não pinta borda no erro.P2ErrorState (retry) + border-danger + aria-invalid.V2
Garantida

Acessibilidade — contraste & breakpoints

Contraste WCAG AA (ratios reais)
ParRatioAA
ink → branco
texto principal
14,6:1
ink-muted → branco
apoio
4,76:1
ink-subtle → branco
header de tabela / labels — REPROVAVA
2,56:1 corrigido
branco → primary
botão primário
6,29:1
branco → canal-vermelho
danger / cancelar
6,47:1
canal-verde (texto) → branco
delta "positivo" — REPROVAVA
3,30:1 corrigido
tags semânticas (fg→bg)
sucesso/aviso/perigo/info
8,2:1
slate-500 → ds-surface
legenda na casca escura — REPROVAVA
3,87:1 corrigido
ds-accent → ds-ink
marcador "ideal"
10,8:1

4 pares reprovavam (texto pequeno < 4,5:1). Todos corrigidos: labels/headers subiram p/ ink-muted, delta verde e legendas da casca ajustados.

Breakpoints (por faixa)
< 640 (sm)
Sidebar recolhe → marca compacta no topbar. Busca global some. KPIs em 1 coluna. Toolbar empilha.
640–1024 (md)
KPIs em 2 colunas. Triagem/Detalhe empilham painel sob a tabela. Tabela rola na horizontal.
≥ 1024 (lg)
Sidebar fixa (244px). KPIs em 4. Master-detail lado a lado. Kanban em board horizontal.
≥ 1280 (xl)
Largura máx. de conteúdo (1240–1320px) centralizada; respiro lateral.
Foco

Ring primary visível em todo controle interativo.

Teclado

role + aria-* em check/switch/tabs/seleção; card do Kanban opera por Enter/Espaço.

Catalogadas & defendidas

Microinterações

Escala de duração
120 · 150 · 200 · 240 · 300ms. Hover instantâneo; entrada suave; "lento" só pra progresso.
3 easings só
standard · ease-out · spring (só o "pop" do check).
Produtivo > expressivo
motion serve à leitura; nunca atrasa o operador.
reduced-motion
respeitado globalmente: corta transform/loop, mantém o que é affordance.
ao vivo · press · toast · check-pop
ao vivo · loading skeleton · sort · drawer
clique no header "Valor" pra ordenar →
ProcessoCanal
SKT0469-SCDIVerdeUSD 48.250
CHB0086-ESDIAmareloUSD 12.900
RCH0002-SCDUVermelhoUSD 91.430
NomeGatilho · regraTempoDefesareduced
btn-presspointerdown · hover troca tom; press recua scale 0.98120ms
ease-out
feedback tátil confirma o clique antes da ação responder (Doherty).mantém cor, corta scale
input-focusfocus · borda primary + ring 2px cresce 0→2120ms
ease-out
marca inequívoca de onde o cursor está — crítico p/ teclado.mantém (é affordance de foco)
row-hoverenter na linha clicável · fundo vira primary-50/40120ms
ease-out
em tabela densa, diz "é esta linha que vou abrir" (Fitts).mantém cor
col-sortclique no header · ArrowUpDown vira seta asc/desc; linhas reordenam150ms
ease-standard
continuidade: mostra para onde cada linha foi.reorder corta; ícone mantém
check-popmarcar · check entra com overshoot leve (scale 0.6→1.12→1)200ms
ease-spring
sensação tátil de "encaixou"; restrito a confirmações.corta (estado final)
tab-underlinetrocar aba · sublinhado realça a aba ativa200ms
ease-standard
continuidade — liga o clique ao conteúdo trocado.corta
drawer-inabrir · painel desliza da direita; backdrop faz fade240ms
ease-standard
a direção mapeia "entrou pela borda"; não tira o foco do board.vira fade
toast-infim da ação · entra de baixo + fade; auto-some200ms
ease-out
fecha o loop ação→confirmação sem bloquear o fluxo.reduz (fade curto)
card-lifthover no card · sobe 2px + sombra cardHover150ms
ease-out
affordance de "clicável" + profundidade leve.corta o translate
skeletonloading · shimmer horizontal contínuo no bloco1.4s loop
linear
comunica "carregando" preservando layout (sem shift).para o shimmer
progress-fillmudança de valor · barra cresce até o %300/500ms
ease-out
semântica de progresso contínuo — só aqui o "lento" cabe.corta a transição
chevron-rotateabrir select · chevron gira 180°150ms
ease-standard
confirma o estado aberto/fechado.corta
O que NÃO animar (restrição é o argumento)
  • Stagger de cards no Kanban — atrasa a leitura de quem varre o board.
  • Reorder animado em lista > ~30 linhas — vira janky e não ajuda.
  • Loops decorativos e page transitions — ferramenta de trabalho, não vitrine.
  • Hover com bounce/elastic — só o check usa overshoot, e com parcimônia.
Vs. os melhores do mundo

Benchmark

Onde o Razac já está bem
  • Tokenização real (zero hex na lógica) com paridade Tailwind ↔ CSS var ↔ catálogo.
  • Token de domínio (DI Canal) como cidadão de 1ª classe — raro e certo.
  • Uma P2Table<T> tipada e única reaproveitada em todas as telas.
  • Foco visível por padrão; documentação viva em camadas (Storybook + /ds-final).
Veredito: tier "consolidando" (2 de 3). Maior alavanca: tokens em 3 camadas.
LacunaReferênciaComo aplicar
Tokens em 3 camadas (primitive → semantic → component)Material 3 · Carbon · ADSA V2 (novas cores) muda só a camada semântica — sem caçar usos. Destrava dark + densidade de uma vez.
Modo de densidade global (compact/comfortable)Carbon · Linear · Antdata-density no shell → tabela, inputs, ícones e paddings reagem juntos. Casa com a marca anti-scroll.
Tabela de classe mundialAnt · Carbon · AG Gridheader sticky + coluna processo congelada + resize + bulk bar + tríade vazio/loading/erro.
Theming light/darkMaterial 3 · Radix · shadcndarkMode por seletor; como o kit só lê tokens semânticos, o dark "cai" sem tocar componente.
Changelog versionado do DSLinear · Carbon · Polarisgerar de components.json history[]; marcar breaking changes. (release-notes.json está vazio.)
Code Connect publicado (Figma↔código)Carbon · Primer · ADSfigmaNodeId já existe; publicar liga o nó do Dev Mode ao snippet P2* real.
Diretrizes de conteúdo / UX writingPolaris (referência mundial)voz/tom, sentence case, formato de processo/moeda, microcopy de erro/vazio com glossário Razac.
As-is → melhorias

Telas atuais

Kanban
  • Faltam 3 das 8 etapas reais (Entrega, Aguardando Nac., Fechamento).
  • Contador da coluna mente sob filtro — mostrar "X de TOTAL".
  • Sem paginação/"ver mais" — board trava no volume real.
  • Atraso deveria herdar danger (vermelho), não warning.
Invoices
  • Filtros/segmented eram estado morto — não filtravam a tabela.
  • Seleção sem ação em lote (bulk bar).
  • Incoterm duplicado (chip + coluna).
  • Toggle "grade" morto.
Detalhe Invoice
  • "Bloqueia DI" bem visível, mas "Conferir" ignorava o bloqueio.
  • Divergência precisa aparecer na linha do item, não só na aba.
Triagem Tributária
  • Alíquota editável que não recalcula — erro fiscal latente.
  • Painel mais raso que o baseline (sem regime por tributo, sem nac × venda).
  • Números de demo desalinhados (KPI ↔ fila ↔ subtítulo).
Nesta rodada

O que já foi aplicado no DS

P2Table: ordenação real (asc/desc + aria-sort), estado de loading (skeleton) e estado vazio nativos.
Acessibilidade de controles: role + aria-checked/pressed/selected + foco e teclado em checkbox, switch, tabs, seleção e card do Kanban.
Contraste WCAG AA: headers/labels/hints subiram de ink-subtle (2,5:1, reprovava) p/ ink-muted; delta verde e legendas da casca corrigidos.
Foco visível padronizado (ring primary) em todos os controles interativos do kit.
Motion: tokens de duração/easing + keyframes (slideInRight, pop, shimmer) e prefers-reduced-motion global.
Drawer desliza da direita (era de baixo) + role="dialog"/aria-modal; backdrop com fade.
P2Toast (feedback de ação) e P2Skeleton novos no kit.
Responsivo: sidebar recolhe < lg c/ marca compacta no topbar; Triagem empilha o painel < lg.

Tudo isso vive no kit @/components/portal2/kit — propaga pro Kanban, Invoices, Detalhe, Triagem e Sala de Testes de uma vez.

Próximo

Roadmap V2

Tokens em 3 camadasprimitive → semantic → component (destrava V2/dark/densidade)prioridade alta
Modo de densidade globaldata-density no shell, toggle Compacto/Confortávelprioridade alta
Tabela world-classsticky header + coluna congelada + bulk bar + paginaçãoprioridade alta
P2ConfirmDialog + P2ErrorStateconfirmação destrutiva + estado de erro com retryprioridade média
Dark modetokens semânticos no escopo darkprioridade média
Code Connect + changelogFigma↔código publicado + novidades versionadasprioridade média
O DS subiu de patamar nesta rodada

Veja a biblioteca endurecida aplicada de ponta a ponta.