Sistema de design — SmartPerformance SFA
Documento humano. A fonte canônica (tokens, regras, checklist) vive em
.claude/docs/design-system.md(MASTER) e a decisão em.claude/docs/decisions.md(ADR-016). Esta página resume para o time.
O frontend (apps/web, Next.js + shadcn/ui + Tailwind) segue a direção "Trust & Authority":
enterprise/B2B, sóbrio, alta legibilidade, WCAG AAA, com light e dark mode. É um app
autenticado data-dense (dashboard, admin, entrada de pedido) — não um site de marketing.
Cores (tokens)
Base slate + accent de marca sky (#0369A1) + status semânticos. Sempre por token
(variável CSS) — nunca #hex no componente.
primary(navy) — botões principais e texto forte.brand(sky) — CTA-chave, links, item de navegação ativo, foco.success/warning/destructive/info— status e feedback.
Status de pedido → pending = warning, success = success, failed = destructive,
rascunho/neutro = muted. Sempre com ícone + texto (nunca só cor).
Tipografia
Plus Jakarta Sans (headings + body). Body ≥ 16px, line-height 1.5. Use tabular-nums
em toda coluna de dados, valor monetário e quantidade.
Layout
App shell: sidebar adaptativa (≥1024px) + topbar + breadcrumbs (3+ níveis) + skip link. Espaçamento em ritmo 4/8px. Um CTA primário por tela.
Componentes
shadcn/ui + ícones Lucide (sem emoji). Tabelas com ordenação, seleção múltipla e ações em massa; formulários com label visível, validação on-blur e erro abaixo do campo. Charts via shadcn Charts (Recharts).
Checklist antes de entregar uma tela
- Sem emoji como ícone; contraste ≥ 4.5:1 em light e dark; foco visível.
- Cor nunca é o único indicador; tokens semânticos;
tabular-numsem dados. prefers-reduced-motionrespeitado; responsivo em 375/768/1024/1440.- Ajuda contextual presente onde o conceito não é óbvio (ver convenção abaixo).
Convenção: tooltips de ajuda ("?")
Ajuda contextual é padrão, não exceção. Três encaixes, todos usando o mesmo primitivo
InfoTooltip (components/ui/info-tooltip.tsx) — ícone "?" acessível (hover + foco + clique,
Esc fecha, role="tooltip"), tema claro/escuro:
- Título de página — passe
helpaoPageHeader. Explique o propósito da tela e as pegadinhas. - Título de modal — passe
helpaoModal. Explique o que aquele fluxo faz. - Campo de formulário — use
FieldLabel(components/ui/field-label.tsx) no lugar deLabelquando o campo merecer nota (formato esperado, efeito colateral, regra de negócio).
Regras de conteúdo: 1–3 frases, foco no porquê/formato, não repita o label. Use <strong>/<em>
com parcimônia e <code> para nomes de campo/JSON. Toda tela/modal/campo não-óbvio novo já nasce
com o "?". Ver também o Tour (onboarding re-acionável) para a visão de fluxo ponta a ponta.
Convenção: campos JSON (visão Tabela | JSON)
Todo campo de formulário que edita um objeto JSON usa o componente KeyValueEditor
(components/integrations/key-value-editor.tsx), com toggle Tabela (key | value) ⇄ JSON.
Nunca use um <textarea> cru para JSON. O editor:
- na tabela, edita pares chave/valor com adicionar/remover linha;
- no JSON, edita o objeto cru (JSON inválido bloqueia a volta à tabela, com aviso);
- preserva tipos na serialização:
200→número,true→boolean,{…}/[…]→aninhado, e strings/templates ({{params.x}}) ficam string.
Aplicado hoje em Integrações (headers, query, params, body, paginação, mapeamento, config de auth).
Quando o valor puder mudar por fora (ex.: autofill ao trocar um select), passe uma key que varie
para remontar o editor. Objetos com aninhamento pesado ficam melhores na visão JSON — o toggle cobre ambos.