vue-componentes/.agent/workflows/ux.global.md

12 KiB

type name description scope updatedAt
workflow ux Revisar e otimizar UX de componentes e telas Vue (Frontend) global 2026-06-01

Workflow: Revisão de UX

Guia de revisão e otimização de interfaces Vue 3 + Vuetify 3 no ecossistema Azteca — para usuários corporativos com baixa familiaridade tecnológica.


Perfil do Usuário

O público-alvo das interfaces é corporativo e diversificado em experiência técnica:

  • Gestores públicos e ambientais
  • Técnicos de campo
  • Consultores ambientais
  • Operadores administrativos

Premissa central: o usuário não tem familiaridade avançada com tecnologia. A interface precisa ser autoexplicativa, sem dependência de treinamento prévio.


Paleta de Cores Institucional

Cor base: #688C00 (verde floresta). Três escalas derivadas: Verde floresta (primária), Âmbar terroso (apoio/aviso), Cinza musgo (neutros). Semânticas independentes para garantir reconhecimento universal.

Escala primária — Verde floresta

Token Hex Stop Uso
--cor-eli-primaria-bg #EEF3D0 50 Fundo de cards destacados, linhas ativas, hover suave
--cor-eli-primaria-zebra #F6F9E8 30 Linha zebrada de tabelas (quase branco esverdeado)
--cor-eli-primaria-suave #BFC99C — Cabeçalho de tabela — sage/olive mudo, sem limão, texto escuro
--cor-eli-primaria-clara #D4E290 100 Badges, chips, seleção, fundo de hover em listas
--cor-eli-primaria-media #ADCC44 200 Tags, indicadores secundários
--cor-eli-primaria-acao #8AAF00 400 Ação secundária, ícones ativos
--cor-eli-primaria #688C00 600 Botões principais, links ativos, destaques — CTA principal
--cor-eli-primaria-escura #4A6500 800 Hover em botões, bordas ativas, títulos com ênfase
--cor-eli-primaria-texto #2E3F00 900 Texto escuro sobre fundos claros da paleta primária

Escala de apoio — Âmbar terroso

Token Hex Stop Uso
--cor-eli-alerta-bg #FAF3DF 50 Fundo de banners de aviso
--cor-eli-alerta-clara #F5DC8A 100 Badges de atenção, chips de alerta
--cor-eli-alerta #DDB847 200 Ícones de aviso, bordas de alerta
--cor-eli-alerta-forte #8C6A00 600 Texto sobre fundo de alerta, status pendente

Escala neutra — Cinza musgo

Token Hex Stop Uso
--cor-eli-fundo #F2F3EE 50 Background geral de páginas
--cor-eli-borda #D5D8CC 100 Bordas padrão de containers
--cor-eli-borda-forte #B5BAA8 200 Bordas de foco, divisores
--cor-eli-neutro #5E6553 600 Textos secundários, ícones inativos
--cor-eli-neutro-escuro #3E4436 800 Texto de label, cabeçalhos de tabela
--cor-eli-superficie #FFFFFF — Cards, modais, popovers

Cores semânticas

Token Hex Uso
--cor-eli-sucesso #2e7d32 Confirmações, status positivo
--cor-eli-sucesso-bg #E8F5E9 Fundo de mensagens de sucesso
--cor-eli-erro #c62828 Erros, ações destrutivas
--cor-eli-erro-bg #FFEBEE Fundo de mensagens de erro
--cor-eli-info #1565c0 Informações auxiliares
--cor-eli-info-bg #E3F2FD Fundo de banners informativos

Regras de contraste

  • Texto sobre --cor-eli-primaria (#688C00) deve ser branco (#ffffff) — contraste 4.6:1 ✓
  • Texto sobre --cor-eli-primaria-bg (#EEF3D0) deve ser --cor-eli-primaria-texto (#2E3F00) — contraste 12:1 ✓
  • Texto sobre --cor-eli-primaria-escura (#4A6500) deve ser branco (#ffffff) — contraste 7.1:1 ✓
  • Texto sobre --cor-eli-alerta-bg (#FAF3DF) deve ser --cor-eli-alerta-forte (#8C6A00) — contraste 5.2:1 ✓
  • Texto sobre --cor-eli-primaria-suave (#BFC99C) deve ser --cor-eli-neutro-escuro (#3E4436) — contraste ~12:1 ✓
  • ⚠️ Efeito limão: --cor-eli-media (#ADCC44) e --cor-eli-acao (#8AAF00) têm saturação 100% no hue amarelo-verde — nunca usar como fundo de cabeçalho. Para fundo verde mudo, usar --cor-eli-primaria-suave.
  • Sempre validar contraste mínimo de 4.5:1 (WCAG AA) para texto normal e 3:1 para texto grande (18px+ ou 14px bold).

Passos

1. Identificar o escopo da revisão

Determinar qual componente, tela ou modal será revisado. Pode ser:

  • Um componente isolado (ex: EliTabela, EliCartao)
  • Uma página completa (ex: PaginaCadastro.vue)
  • Um modal ou drawer (ex: EliTabelaModalFiltroAvancado.vue)
  • Uma interação específica (ex: fluxo de filtro, paginação, menu de ações)

2. Mapear o estado atual

Antes de alterar, entender o que já existe:

  • Ler o template (<template>) para entender a estrutura visual
  • Ler o CSS/SCSS associado para mapear os tokens de design em uso
  • Identificar quais componentes Vuetify estão sendo utilizados (ex: v-btn, v-dialog, v-select)
  • Verificar se existem estilos inline que deveriam migrar para classes CSS

3. Avaliar contra os critérios de UX

Para cada elemento da interface, avaliar:

Clareza

  • O propósito de cada elemento é óbvio sem instrução?
  • Labels e placeholders são descritivos? (ex: "Buscar por nome ou CPF" vs "Buscar")
  • Ícones acompanham texto quando a ação não é universalmente reconhecível?
  • O estado vazio (empty state) orienta o usuário sobre o próximo passo?

Hierarquia visual

  • O olho do usuário é guiado para a ação principal primeiro?
  • Ações primárias usam --cor-eli-primaria (#688C00) com destaque?
  • Ações secundárias são visuais mas não competem com a primária?
  • Ações destrutivas (Excluir, Limpar) usam --cor-eli-erro com variante text ou outlined?

Feedback e estados

  • Botões têm estados claros de hover (--cor-eli-primaria-escura), focus e disabled (--cor-eli-borda-forte)?
  • Carregamentos exibem indicador visual (spinner, skeleton, barra de progresso)?
  • Erros de formulário aparecem próximos ao campo com mensagem descritiva, usando --cor-eli-erro + --cor-eli-erro-bg?
  • Sucesso de operações tem confirmação visual (snackbar, toast, badge) com --cor-eli-sucesso?

Densidade e espaçamento

  • O espaçamento segue múltiplos de 4px (4, 8, 12, 16, 24, 32)?
  • Em desktop, o espaço horizontal é bem aproveitado? (ex: grids de 2+ colunas para formulários largos)
  • Em mobile, os elementos empilham verticalmente sem quebra visual?
  • Modais têm largura proporcional ao conteúdo?

Tipografia

  • Tamanhos de fonte seguem a escala: 12px (caption), 14px (body), 16px (subtitle), 20px (title), 24px (heading)?
  • Textos longos usam line-height: 1.5 para legibilidade?
  • Labels de formulário são visualmente distintos do conteúdo preenchido?

Acessibilidade básica

  • Elementos interativos têm aria-label quando o texto visual não é suficiente?
  • Foco via teclado (Tab) segue uma ordem lógica?
  • Cores não são o único meio de comunicar estado (ex: ícone + cor para erro)?
  • Todo texto sobre cor primária ou escura usa branco (#FFFFFF)?
  • Todo texto sobre --cor-eli-primaria-bg usa --cor-eli-primaria-texto (#2E3F00)?

4. Aplicar padrões Vue/Vuetify do projeto

Ao implementar melhorias, seguir os padrões do ecossistema:

Componentes Vuetify

  • Usar v-btn com variantes do tema (color="primary") em vez de classes CSS manuais para botões
  • Usar v-dialog para modais, v-menu para popovers contextuais
  • Usar v-text-field, v-select etc. para inputs sempre que possível
  • Aproveitar props de Vuetify: density, variant, rounded, elevation

Iconografia — Lucide (obrigatório)

Todos os ícones do projeto devem vir exclusivamente da biblioteca @lucide/vue (dependência já instalada no package.json).

Proibido:

  • SVG inline manual (hardcoded no template)
  • Ícones de @mdi/font ou Material Design Icons em componentes do projeto
  • Bibliotecas alternativas (Font Awesome, Heroicons, etc.)

Como usar:

<script lang="ts">
import { Filter, Plus, X, Trash2, Eye } from "@lucide/vue"
</script>

<template>
  <!-- Uso direto como componente -->
  <Filter :size="18" :stroke-width="2" />

  <!-- Dentro de botão -->
  <button>
    <Plus :size="15" :stroke-width="2.5" />
    Adicionar
  </button>
</template>

Props úteis: :size (número em px), :stroke-width (espessura do traço, padrão 2), :color (cor do ícone).

Catálogo de referência: https://lucide.dev/icons — buscar pelo nome do ícone em inglês.

Os tokens CSS estão documentados nas tabelas da seção Paleta de Cores Institucional acima. No código, usar var(--token, #fallback) — sempre com fallback hardcoded em componentes de biblioteca.

  • Classes devem seguir BEM: eli-componente__elemento--modificador
  • Evitar !important — resolver especificidade via seletor mais específico
  • Usar var(--cor-eli-primaria) em vez de valores hex hardcoded no CSS dos componentes
  • Transições padrão: transition: all 0.2s ease para hover/focus

Composição de componentes

  • Componentes filhos devem receber dados via props e emitir eventos via $emit
  • Evitar acessar o DOM diretamente; preferir ref do Vue
  • Não duplicar CSS entre componentes — extrair para classe utilitária ou CSS do componente pai

5. Implementar melhorias prioritárias

Ordenar as melhorias por impacto no usuário:

  1. Crítico: elementos que causam confusão ou impedem o uso (falta de feedback, botão invisível, estado vazio sem orientação)
  2. Alto: melhorias que reduzem atrito (espaçamento, hierarquia de botões, responsividade)
  3. Médio: refinamentos visuais (transições, micro-animações, consistência de cores)
  4. Baixo: polish (sombras sutis, arredondamentos, tipografia refinada)

6. Validar resultado

Após implementar:

  • A tela renderiza sem erros no console?
  • Os estados (vazio, carregando, erro, com dados) estão todos cobertos?
  • A paleta de cores está coerente com a base #688C00?
  • Todos os tokens usados estão definidos na escala primária, de apoio ou neutra?
  • Nenhuma cor está hardcoded no CSS do componente (usar var(--token, #fallback))?
  • Tokens novos têm fallback hardcoded? (ex: var(--cor-eli-primaria-suave, #BFC99C))?
  • Contraste de texto validado: branco sobre --cor-eli-primaria e --cor-eli-primaria-escura; --cor-eli-neutro-escuro sobre --cor-eli-primaria-suave?
  • Nenhuma ação ficou sem feedback visual?
  • O layout não quebra em larguras menores que 1024px?
  • Componentes Vuetify recebem props de tema (color, variant) em vez de override CSS?
  • Efeito zebra de tabelas tem fundo branco explícito nas linhas normais (para funcionar sobre qualquer fundo de página)?

Anti-padrões a evitar

❌ Anti-padrão ✅ Alternativa
Botão sem label de texto Botão com ícone + texto, ou aria-label descritivo
Cor vermelha para ação primária Vermelho apenas para destrutivas; primária usa --cor-eli-primaria
Modal com scroll interno extenso Dividir em etapas ou usar drawer lateral
Tabela com 15+ colunas visíveis Usar o modal de colunas para esconder as menos usadas
Placeholder como único label Label fixo acima do campo + placeholder como exemplo
Ações alinhadas à esquerda em linha de tabela Ações à direita, próximas ao fim da linha visual
Toast/snackbar sem ação de fechar Sempre incluir botão de fechar ou auto-dismiss com tempo suficiente (5s+)
Estilos inline em <template> Migrar para <style scoped> com classe BEM
Cor hex hardcoded no componente Usar var(--cor-eli-primaria) e demais tokens com fallback
Texto escuro (#333) sobre --cor-eli-primaria Usar branco (#FFFFFF) para garantir contraste WCAG AA
Amarelo/âmbar para sucesso Âmbar é reservado para aviso; sucesso usa --cor-eli-sucesso (#2E7D32)
Misturar stops da paleta fora dos tokens Usar apenas os tokens definidos; nunca interpolar valores avulsos
Usar --cor-eli-media ou --cor-eli-acao como fundo de cabeçalho Usar --cor-eli-primaria-suave (#BFC99C) — verde mudo sem efeito limão
var(--token) sem fallback em componente de biblioteca Sempre declarar var(--token, #valor) — o projeto destino pode não ter o token atualizado
Zebra de tabela sem fundo branco explícito nas linhas normais Declarar .eli-tabela__tr .eli-tabela__td { background: var(--cor-eli-superficie, #fff) } antes da regra zebra