DESIGN.md
O DESIGN.md reúne, em um único arquivo de texto, as decisões visuais e de interface do MDS: cores, tipografia, espaçamento, elevação, formas, componentes-chave, estilo de escrita e as diretrizes de comportamento (estados, feedback, ações destrutivas, formulários e navegação). É o contexto que uma IA precisa para gerar telas que parecem e se comportam como o produto.
Como usar
Seção intitulada “Como usar”- Em ferramentas de código (Claude Code, Cursor e similares): baixe o arquivo e salve como
DESIGN.mdna raiz do projeto, para o agente ler antes de gerar ou alterar interface. - Em geradores de interface (Google AI Studio, Lovable, v0 e similares): cole o conteúdo nas instruções do projeto ou anexe o arquivo como conhecimento.
- Para classes CSS exatas, combine com o pacote
@mobiis/mds-style(o DESIGN.md descreve as decisões; as classesmds-*vêm do CSS).
O arquivo é gerado do CSS real e das diretrizes do MDS. Quando o sistema mudar, baixe de novo.
Conteúdo
Seção intitulada “Conteúdo”1. Overview
O Mobiis Design System (MDS) é a linguagem visual do ecossistema de logística integrada da Mobiis (TMS, YMS, WMS, roteirização, rastreamento de frota e a assistente MIA). O público é operacional e técnico — operadores logísticos, motoristas, gerentes de pátio, diretores de supply chain — e a interface precisa sustentar alta densidade de dados em tempo real sem parecer poluída.
Diretriz central: simplificar e revelar informação progressivamente. Mostre apenas o que é pertinente para a ação do momento; deixe o sistema fazer o trabalho pesado e o usuário no controle. Cada tela tem um objetivo principal (Lei de Hick: mais opções visíveis = mais tempo de decisão).
Princípios formais do MDS (fonte: docs/principios-de-design.md):
- Questionamos — O trabalho deve ter um propósito - procuramos abordar problemas reais e urgentes que as pessoas estão enfrentando. Questionamos até entender claramente o núcleo do problema antes de gastar um pouco de tempo no desenvolvimento de soluções. Questionamos afim de não perder tempo resolvendo os problemas errados.
- Clareza — Para uma interface ser eficaz e eficiente, o usuário deve ser capaz de reconhecer a sua utilidade e entender como ela pode ajudá-lo, prever o que vai acontecer durante o uso, e conseguir interagir com sucesso. Não há motivos para mistérios nas interfaces. Clareza inspira confiança e cativa o uso.
- Objetividade — O tempo que leva para fazer uma decisão aumenta com o número de opções apresentadas. (Lei de Hick)
- Consistência — Padronização de componentes, comportamentos e funcionalidades. Comportamento igual para itens semelhantes. “Se parece um botão, deve se comportar como um botão”.
Identidade técnica: BEM estrito com prefixo mds- em todo componente (.mds-btn, .mds-card__header, .mds-btn--primary), enquanto fundações e utilitários (grid, spacing, texto) usam nomes “limpos” no padrão Bootstrap/Tailwind (.container, .gap--md, .text-muted) para reduzir a curva de aprendizado. Tudo — com ou sem prefixo — resolve para os mesmos design tokens (CSS Custom Properties --mds-*), então a consistência visual é garantida mesmo nas classes sem prefixo.
Multi-marca: O sistema suporta múltiplos tenants/produtos trocando só a cor primária via [data-primary="..."] no elemento raiz. O padrão (sem atributo) é brand-mobiis. Um agente que gerar UI para um cliente específico deve preservar essa variável, nunca fixar a cor em hexadecimal.
2. Colors
Todas as cores são CSS Custom Properties (--mds-colors-*), nunca hex fixo no HTML/CSS de consumo. Cada papel semântico tem 5 tons (lighter, light, main, dark, darker) + seu par de contraste — nomenclatura alinhada ao Figma (--mds-colors-<papel>-<tom> para o fundo, --mds-colors-<papel>-on-<tom> para o texto/ícone legível sobre ele, ex.: --mds-colors-primary-main + --mds-colors-primary-on-main).
Papéis semânticos (tema claro)
| Papel | Token base | lighter |
light |
main |
dark |
darker |
Quando usar |
|---|---|---|---|---|---|---|---|
| Primary | --mds-colors-primary-* |
#ecf3ff |
#a0c4fd |
#408afa |
#3068bb |
#20457d |
Ação principal, marca, item ativo/selecionado, foco de interação |
| Secondary | --mds-colors-secondary-* |
#e9ebf3 |
#939ac5 |
#27348b |
#1d2768 |
#141a46 |
Marca institucional, badges/destaques secundários, campo válido (borda) |
| Danger | --mds-colors-danger-* |
#fcebe6 |
#f29980 |
#e53200 |
#ac2600 |
#731900 |
Erro, exclusão, bloqueio, ação irreversível |
| Warning | --mds-colors-warning-* |
#fef9e6 |
#f8e280 |
#f0c400 |
#b49300 |
#786200 |
Atenção, campo obrigatório, dado pendente de revisão |
| Info | --mds-colors-info-* |
#e6f3fb |
#80c3ed |
#0087db |
#0065a4 |
#00446e |
Mensagem neutra, dica, estado informativo sem urgência |
| Success | --mds-colors-success-* |
#e6f9e6 |
#80e381 |
#00c703 |
#009502 |
#006402 |
Confirmação, conclusão, dado validado |
on-<tom> é a cor de texto/ícone garantida legível sobre aquele fundo — sempre use o par (--mds-colors-<papel>-main + --mds-colors-<papel>-on-main), nunca aplique texto escuro fixo sobre um fundo de token.
✅ Checagem cruzada com o Figma (2026-09-22, Design System 2.0): Os fundos (
lighter/main/dark/darker) batem exatamente com o Figma em todas as 12 famílias (primary, secondary, danger, warning, success, info, aqua, blue, green, orange, pink, red, teal, yellow) e na escala de cinza inteira.Corrigido em
src/scss/themes/_light.scssem 2026-09-22 (reproduzindo a fórmula desrc/stories/foundations/TokenManager.stories.ts,generateScale: tomlight= passo200= 50% de mistura da cor-base com branco): o tomlightde Primary/Secondary estava desatualizado.
--mds-colors-primary-light: era#70a7fb, agora#a0c4fd.--mds-colors-primary-on-light: era#020408, agora#060e19(par de contraste do tom acima, ajustado junto para continuar legível).--mds-colors-secondary-light: era#5d67a8, agora#939ac5.--mds-colors-secondary-on-light: era#f9f9fc, agora#010204(par de contraste do tom acima, ajustado junto para continuar legível).Achado à parte, ainda em aberto (não corrigido): Figma:
on-main/on-dark/on-darker= o próprio tomlighterdo papel. CSS: um quase-branco específico do papel, próximo mas não idêntico aolighter.
primary: CSS#f9fbff, Figma reaproveita olighter(#ecf3ff).secondary: CSS#f9f9fc, Figma reaproveita olighter(#e9ebf3). Confiança: alta para primary/secondary (zoom dedicado); padrão, não confirmado byte a byte, nos demais papéis.
Background / Surface / Text (neutros)
Escala base: --mds-colors-gray-0 #fefefe … --mds-colors-gray-50 #fafbfc … --mds-colors-gray-100 #f3f4f6 … --mds-colors-gray-200 #e8eaee … --mds-colors-gray-300 #dcdfe5 … --mds-colors-gray-400 #d0d4dc … --mds-colors-gray-500 #9c9fa5 … --mds-colors-gray-600 #686a6e … --mds-colors-gray-700 #343537 … --mds-colors-gray-800 #151516 … --mds-colors-gray-900 #060607.
| Uso | Token | Valor | Regra |
|---|---|---|---|
| Surface / Card | --mds-dimmed-default |
#fefefe |
Fundo padrão de card, modal, painel — “branco” do sistema |
| Background (página) | --mds-colors-background-light |
#fafbfc |
Fundo da aplicação por trás dos cards |
| Background (elemento) | --mds-colors-background-main |
#f3f4f6 |
Fundo de blocos secundários (ex.: .mds-box) |
| Background (rebaixado) | --mds-colors-background-dark |
#e8eaee |
Hover neutro, divisores de área, estado “dimmed” |
| Border | --mds-colors-ui-border |
#e8eaee |
Toda borda 1px de card, input, tabela |
| Text — corpo (padrão) | --mds-colors-foreground-main |
#686a6e |
Texto de parágrafo, valor de dado, corpo em geral |
| Text — ênfase/secundário | --mds-colors-foreground-dark |
#343537 |
Título, rótulo em destaque, texto que precisa de mais peso que o corpo |
| Text — muted/apoio | --mds-colors-foreground-light |
#9c9fa5 |
Placeholder, texto de ajuda, timestamp, metadado de baixa prioridade |
Note a inversão de intuição:
foreground-darké o texto de MAIOR ênfase (mais escuro = mais peso), eforeground-lighté o texto de MENOR ênfase (mais claro = apoio). Siga essa semântica, não o nome literal.
Destructive
Não existe token destructive isolado — Danger cobre esse papel (botão de exclusão = variant="danger" / .mds-btn--danger, --mds-colors-ui-danger = #e53200).
Overlay / Shadow
--mds-colors-ui-shadow:rgba(22, 22, 23, 0.15)— base de toda sombra do sistema.--mds-colors-background-transparency:rgba(52, 53, 55, 0.6)— backdrop de modal/drawer.
Multi-marca ([data-primary="..."])
| Tenant | Cor main |
|---|---|
brand-mobiis |
#408afa |
brand-log |
#64be50 |
blue |
#0087db |
teal |
#00dbdb |
aqua |
#00f0b8 |
green |
#00c703 |
yellow |
#f0c400 |
orange |
#f07800 |
red |
#e53200 |
pink |
#ff0073 |
Tema escuro
[data-theme="dark"] e :root aplicam-se ao mesmo elemento — uma prop não redeclarada em [data-theme="dark"] cai para o valor de :root (cascata normal do CSS); a maioria dos papéis redeclara os 5 tons com valores próprios para dark. Ex.: primary-main é #408afa no claro e #3068bb no escuro. Neutros do tema escuro: fundo #001027, texto de corpo #8090a7. Um agente de IA nunca deve ler valor de cor fixo: sempre referenciar o token, para funcionar nos dois temas automaticamente.
🧮 Primary/Secondary do tema escuro: calculados, não conferidos ao vivo no Figma (2026-09-22). Não existe página de dark mode no arquivo Figma. Fórmula + mapeamento de
src/stories/foundations/TokenManager.stories.ts(generateScale,selectOnColor/APCA,semanticMappingsDark), rodados com Node (apca-w3/culori, as mesmas libs da story) — não lidos de um Figma consultado ao vivo.Mapeamento aplicado (
semanticMappingsDark):lighter=passo 700,light=passo 600,main=passo 500,dark=passo 300,darker=passo 200.Primary (
src/scss/themes/_dark.scss):
lighter:#20457d→#10223f;on-lighter:#f9fbff→#ecf3fflight:#3068bc→#20457d;on-light:#f9fbff→#ecf3ffmain:#408afa→#3068bb;on-main:#f9fbff→#ecf3ffdark:#a0c5fd→#70a7fb;on-dark:#020408→#020408darker:#cfe2fe→#a0c4fd;on-darker:#020408→#060e19Secondary (src/scss/themes/_dark.scss):lighter:#141a46→#0a0d23;on-lighter:#f9f9fc→#e9ebf3light:#1d2768→#141a46;on-light:#f9f9fc→#e9ebf3main:#27348b→#1d2768;on-main:#f9f9fc→#e9ebf3dark:#939ac5→#5d67a8;on-dark:#f9f9fc→#e9ebf3darker:#c9cce2→#939ac5;on-darker:#010204→#010204⚠️ O CSS anterior de dark já usava outro mapeamento de passo (lighter=600, light=500, main=400, dark=200, darker=100) — diferente do declarado no Token Manager.
mainmuda de valor visível de forma perceptível (não só um ajuste de contraste): de#408afa(idêntico ao main do tema claro) para#3068bb, mais escuro. ⚠️ Sem página de dark no Figma, não há como confirmar visualmente — só a fórmula do gerador garante a consistência.
3. Typography
Fonte: "Manrope", system-ui, -apple-system, "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji". Token: --mds-font-family.
Pesos: --mds-font-weight-light 300 · --mds-font-weight-normal 400 · --mds-font-weight-semibold 600 · --mds-font-weight-bold 700 (peso padrão de botões: semibold).
Escala de tamanho (--mds-font-size-*)
| Token | px |
|---|---|
xs |
12 |
sm |
14 |
md |
16 |
lg |
20 |
xl |
24 |
xxl |
32 |
xxxl |
40 |
hg |
48 |
xhg |
56 |
xxhg |
64 |
Hierarquia semântica (classes atuais, prefixo mds-)
| Classe | Tamanho | Peso | Line-height |
|---|---|---|---|
.mds-headline--h1 |
64px | 700 | 125% |
.mds-headline--h2 |
48px | 700 | 125% |
.mds-headline--h3 |
32px | 700 | 125% |
.mds-headline |
24px | 700 | 125% |
.mds-headline--h4 |
24px | 700 | 125% |
.mds-title--lg |
20px | 700 | 125% |
.mds-title |
16px | 700 | 125% |
.mds-title--md |
16px | 700 | 125% |
.mds-title--sm |
14px | 700 | 125% |
.mds-body--lg |
20px | 400 | 150% |
.mds-body |
16px | 400 | 150% |
.mds-body--md |
16px | 400 | 150% |
.mds-body--sm |
14px | 400 | 150% |
.mds-body--xs |
12px | 400 | 150% |
Classes legadas (sem prefixo, @deprecated no SCSS — não usar em código novo)
| Classe | Tamanho | Peso | Line-height |
|---|---|---|---|
.display2 |
40px | 300 | 125% |
.display |
32px | 700 | 125% |
.title |
24px | 400 | 125% |
.subtitle |
20px | 700 | 125% |
.body |
16px | 400 | 150% |
.small |
14px | 400 | 150% |
.caption |
14px | 700 | 125% |
.helper-text |
12px | 400 | 150% |
Também existem diretivas Angular equivalentes às classes atuais: mdsHeadline="h1|h2|h3|h4", mdsTitle="lg|md|sm", mdsParagraph="lg|md|sm|xs".
Classes utilitárias de alinhamento/transformação de texto (
.text-left,.text-uppercase…) não são conceito de tipografia — são utilitário de fundação. Lista exata na skillmds-style(agent-skills/SKILL.md), seção “Utility Classes Cheat Sheet”.
4. Layout & Spacing
Base: grid inspirado em Bootstrap (.container, .container-fluid, .row, .col-[n], breakpoints xs/sm/md/lg/xl/xxl), sem prefixo mds- (é fundação, não componente).
Densidade: média-alta — o produto prioriza mostrar mais dado por tela (tabelas, kanbans, cards compactos) mantendo respiro suficiente para uso prolongado.
Escala de espaçamento (--mds-spacing-*)
| Token | px |
|---|---|
xs |
4 |
sm |
8 |
md |
16 |
lg |
24 |
xl |
32 |
xxl |
40 |
xxxl |
48 |
md (16px) é o padrão quando nenhum tamanho é especificado.
As classes utilitárias que aplicam esta escala (
.padding-{pos}--{tam},.margin-{pos}--{tam},.gap--{tam},.d-flexe o resto do grid/flexbox) são utilitário de fundação, não conceito de spacing — catálogo exato na skillmds-style(agent-skills/SKILL.md), seção “Utility Classes Cheat Sheet”.
5. Elevation & Depth
Sombra em 5 níveis, todas usando a mesma cor-base, variando só o espalhamento — cresce junto com a escala de espaçamento:
| Nível | Classe | box-shadow |
|---|---|---|
| 1 | .mds-elevation--1 (ou .elevation--1) |
0 1px 1px rgba(22, 22, 23, 0.15) |
| 2 | .mds-elevation--2 (ou .elevation--2) |
0 2px 4px rgba(22, 22, 23, 0.15) |
| 3 | .mds-elevation--3 (ou .elevation--3) |
0 4px 8px rgba(22, 22, 23, 0.15) |
| 4 | .mds-elevation--4 (ou .elevation--4) |
0 8px 16px rgba(22, 22, 23, 0.15) |
| 5 | .mds-elevation--5 (ou .elevation--5) |
0 16px 24px rgba(22, 22, 23, 0.15) |
Blur (glassmorphism pontual — não é padrão de fundo): --mds-blur-xs 8px · --mds-blur-sm 16px · --mds-blur-md 32px · --mds-blur-lg 48px · --mds-blur-xl 64px, via .blur--{tam} (backdrop-filter).
Divisores: linha 1px sólida na cor de borda (não sombra) — usada em vez de elevação para separar seções de mesma superfície.
Motion: transições de estado (hover/active/expand) usam 0.2s com easing cubic-bezier(0.645, 0.045, 0.355, 1) — perceptível mas rápido, sem “bounce”.
6. Shapes & Borders
Cantos padronizados em escala própria (não ligada à escala de spacing, apesar de nomes iguais):
| Token | px |
|---|---|
xxs |
4 |
xs |
6 |
sm |
8 |
md |
16 |
lg |
24 |
xl |
32 |
xxl |
40 |
xxxl |
48 |
Raio por família de componente (extraído do SCSS de cada um — não presuma)
| Elemento | Raio | Fonte |
|---|---|---|
Botão (md, padrão) |
8px (--mds-radius-sm) |
tokens/_components.scss |
| Input / Select (padrão) | 8px (--mds-radius-sm) |
mixins/_fields.scss:33 (parâmetro padrão do mixin) |
| Card | 8px (--mds-radius-sm) |
components/_card.scss:12 |
Modal (mds-float-panel--modal) |
8px (--mds-radius-sm) |
components/_float-panel.scss:189 |
Drawer / tela cheia (--fullscreen) |
0px (sem raio — encosta na borda da viewport) | components/_float-panel.scss:226 |
| Avatar (padrão) | 8px, quadrado arredondado (não é círculo por padrão) | components/_avatar.scss:23 |
Avatar .mds-avatar--rounded |
100% (círculo completo) | components/_avatar.scss:30 |
| Checkbox | 6px (--mds-radius-xs) |
components/_checkbox.scss:4 (parâmetro padrão do mixin) |
| Switch/Toggle | 40px (--mds-radius-xxl, pill) |
components/_checkbox.scss:42 (parâmetro padrão do mixin) |
A maioria dos componentes de formulário/superfície (botão, input, select, card, modal, checkbox) usa o mesmo raio pequeno (
--mds-radius-sm, 8px, ou--mds-radius-xs, 6px, no checkbox) — não há um raio “de input” desproporcionalmente maior; só avatar--roundede switch/toggle chegam a formas totalmente arredondadas.
Borda: 1px sólida como padrão (--mds-colors-ui-border ou --mds-control-default-border); campo em foco/erro sobe para 2–3px com a cor semântica. Nunca use outline do navegador puro — o MDS estiliza o próprio anel de foco.
7. Key Components
Botões (.mds-btn)
| Tamanho | Altura | Raio | Fonte do botão |
|---|---|---|---|
xxs |
12px | --mds-radius-xxs |
— (sem botão nesse tamanho) |
xs |
24px | --mds-radius-xs |
12px |
sm |
32px | --mds-radius-sm |
12px |
md |
48px | --mds-radius-sm |
14px |
lg |
56px | --mds-radius-sm |
16px |
- Peso de texto sempre semibold (600), independente do tamanho (fonte:
components/_button.scss:18). - Variantes de cor:
control/default(neutro, cinza),primary,secondary,danger,warning,success,info,transparent/link(sem fundo, ação de baixa prioridade). Regra de produto: no máximo 1 botãoprimarypor tela/formulário/diálogo. - Modificadores:
outline(contorno, sem fundo sólido),rounded(pill),loading(loader substitui o conteúdo, botão inerte),disabled. - Botão só-ícone precisa de
aria-label/tooltip — nunca um botão mudo visualmente.
Inputs / Campos de formulário
- Raio padrão igual ao de botões e cards (8px) — não é mais arredondado que o resto do sistema.
- Estado padrão: fundo branco (surface), borda 1px na cor de borda padrão.
- Foco/ativo: borda sobe para a cor
primary; erro: borda + sombra emdanger; obrigatório pendente: destaque emwarning; válido: bordasecondary-dark. - Rótulo acima do campo (não usa placeholder como rótulo); texto de ajuda abaixo, cor muted.
Cards
- Fundo surface, raio 8px, elevação 1 em repouso, sobe ao hover/seleção.
- Cabeçalho (
mdsCardHeader) arredonda só o topo; corpo e rodapé (mdsCardFooter) seguem o mesmo raio do card. - Notificação/atualização: badge sólido no canto; seleção em lote: checkbox + anel de destaque (
box-shadow: 0 0 0 2pxna cor do estado).
Modais e Drawers (mds-float-panel)
- Modal (
--modal): raio 8px, elevação alta, backdrop escuro translúcido. Diálogo central, para interrupção/confirmação/detalhe que exige foco total. - Drawer (
--drawer): painel lateral sem raio (encosta na borda), para fluxos de formulário que devem manter contexto da tela por trás. - Tela cheia (
--fullscreen): raio zerado explicitamente. - Ações sempre no rodapé, fixas; título curto; fechamento por “×” ou clique no backdrop.
Navegação (Topbar / Menu / Tabs)
- Topbar: altura fixa 64px. Menu lateral: 256px expandido, 64px compacto (só ícones), altura de item 64px.
- Item ativo com fundo
item-active-background(tom claro deprimary) e borda/textoprimary-dark. - Abas (
nav-tabs): item ativo com peso bold e indicador emprimary; nunca mais de 2 níveis de profundidade em menus/dropdowns.
Ícones
- Sistema Lucide (SVG), consumido por alias semântico em português no Angular (ex.:
icon="excluir") — nunca pelo nome literal do ícone Lucide. - Tamanhos alinhados à escala de fonte (
sm/md/lg/xl), herdam a cor do texto/ícone do contexto (currentColor).
8. Voice & Writing
O texto da interface é lido em movimento (pátio, doca, celular do motorista), por quem quer saber o que aconteceu com a carga e o que fazer agora. Todo texto gerado para o MDS segue as regras abaixo — inclusive rótulos, placeholders, mensagens e dados de exemplo em protótipos.
Princípios
| Princípio | Regra |
|---|---|
| Direto | A informação mais importante vem primeiro. |
| Preciso | Diga qual carga, placa ou documento e quanto; nada de “ocorreu um erro”. |
| Neutro | Voz do sistema: sem “você”, “eu” ou “nós”; sem “Ops”; sem exclamação. |
| Familiar | Vocabulário do operador (Carga, Viagem, Manifesto, Pátio, Doca), não o do banco de dados. |
| Consistente | Um conceito, um nome, em todas as telas. |
Estrutura da mensagem
Mensagem de feedback = o que aconteceu (com o objeto específico) + o que fazer (se houver). Ex.: “CPF inválido. Insira apenas números.” — nunca “Você digitou o CPF errado.” nem “Ocorreu um erro.”
Capitalização
| Elemento | Estilo | Exemplo |
|---|---|---|
| Botão | Título | Confirmar Entrega |
| Título de página/modal/drawer/EmptyState | Título | Excluir Rota? |
| Item de menu e aba, cabeçalho de coluna de tabela | Título | Agendamento de Docas · Data de Entrega |
| Rótulo de campo, placeholder | Sentença | Nome do motorista |
| Toast, Alert, erro, Tooltip, texto de carregamento | Sentença | Falha na conexão. |
| Descrição e texto de ajuda, status/badge | Sentença | Em trânsito |
Caixa de título: cada palavra significativa em maiúscula; artigos, preposições e conjunções (a, o, de, da, em, para, por, com, e, ou…) em minúscula (Ir para o Dashboard). Caixa de sentença: só a primeira palavra e nomes próprios; siglas mantêm a grafia (NF-e, CPF). Nunca digite texto em CAIXA ALTA — se o design pedir maiúsculas, é estilo (CSS). (a validar: A regra por classe gramatical adapta ao português a regra “AP” (palavras com mais de 3 letras) hoje descrita nas Diretrizes.)
Regras de rótulo, pontuação e vocabulário
- Botão: verbo no infinitivo + objeto, 1–2 palavras (Salvar, Emitir Nota, Despachar Carga); sem repetir o contexto da seção (seção “Motoristas” → Adicionar). Em confirmação, o botão repete a ação (Excluir Rota), nunca “Sim”/“OK”; a saída é Cancelar.
- Reticências (…) no botão/item que abre outra janela ou pede mais dados antes de concluir (Configurar Filtros…); nunca em placeholder, tooltip ou item de submenu. Use o caractere único …, não três pontos.
- Ponto final em mensagens e descrições (Toast, Alert, erro, EmptyState); sem ponto em rótulo, botão, título, placeholder, status e tooltip de uma frase. Pergunta sempre termina com “?”.
- Status descreve onde a coisa está (particípio/expressão curta: Despachada, Em trânsito, Aguardando doca); ação descreve o que vai acontecer (infinitivo); processo em andamento é gerúndio + reticências (Gerando relatório…).
- Verbo padrão por ação: Salvar, Excluir (definitivo), Cancelar (interrompe e mantém histórico), Pesquisar, Confirmar/Registrar/Concluir, Despachar, Emitir (documento fiscal). Não alterne com sinônimos (Deletar, Apagar, Buscar, Submeter).
- Siglas: as de todo operador (NF-e, CT-e, MDF-e, CPF, CNPJ, CEP, ETA) valem sem explicação; as demais vêm por extenso ou em Tooltip (ICMS → “Imposto sobre circulação de mercadorias”). Termo em inglês só se for nome de produto ou uso corrente do setor.
- Link descreve o destino (“Ver detalhes da carga”), nunca “Clique aqui”. Botão só-ícone sempre com
aria-labele Tooltip. - Plural e gênero corretos, sem “(s)”: “1 carga”, “12 cargas”, “Nenhuma carga”. Cada frase é uma string inteira — nunca montada por concatenação.
Formatos (pt-BR)
| Tipo | Formato | Exemplo |
|---|---|---|
| Data | dd/mm/aaaa | 25/09/2026 |
| Hora | 24 h | 14:30 |
| Moeda | R$, ponto no milhar, vírgula nos centavos | R$ 1.250,90 |
| Peso, volume, distância | Número, espaço, unidade | 1.250 kg · 32,5 m³ · 142 km |
| Duração | Unidade abreviada, sem ponto | 45 min · 2 h 10 min |
| Placa | Com hífen (antiga); sem hífen (Mercosul) | ABC-1234 · ABC1D23 |
| CEP / CPF | Com máscara | 00.000-000 · 000.000.000-00 |
Evite → Prefira
| Evite | Prefira |
|---|---|
| Sua carga foi despachada com sucesso agora. | Carga despachada. |
| Tem certeza que quer apagar? | Título “Excluir Rota?” + botões Cancelar · Excluir Rota |
| Ops, nada por aqui! | Nenhuma Viagem Encontrada. Não há viagens para o filtro selecionado. |
| Por favor, aguarde enquanto carregamos… | Carregando viagens… |
| Não foi possível agendar. | Doca 3 indisponível às 14h. Escolha outro horário. |
| Digite aqui o nome do motorista… | Nome do motorista |
Ainda em aberto (a validar com Produto)
- Termos oficiais do domínio (Carga, Viagem, Doca, Check-in/Check-out…) e o verbo Remover (tirar um item de uma lista ou vínculo sem apagá-lo) ainda precisam ser fechados com Produto e Operações.
- Mostrar o fuso horário explicitamente em telas que operem em mais de um fuso.
9. Interface Guidelines
Estas diretrizes são direcionamento, não livro de regras: desviar é permitido, desviar sem saber por quê não. Quando duas regras conflitarem, desempate nesta ordem — Clareza › Consistência › Objetividade (e antes de tudo, confirme que o problema é o certo). Se nenhum padrão serve, procure um componente existente no MDS antes de inventar; nunca crie estilo local “quase igual” ao do sistema.
Regras de comportamento e composição de tela (o “como a interface deve se comportar”), complementares às seções visuais 2–7 e ao estilo de escrita da seção 8. Fonte: seção Guidelines do docs-site. Itens marcados (proposta) ainda não foram validados com Produto — aplique, mas não trate como regra fechada.
9.1 Princípios aplicados a uma tela
| Princípio | Como aplicar | Teste |
|---|---|---|
| Questionamos | Parta do problema da pessoa (“quem quer fazer o quê e o que impede”), não da tela pedida. | Consigo dizer qual problema isto resolve sem citar tela ou componente? |
| Clareza | Toda tela responde: onde estou (título, breadcrumb, item ativo), o que posso fazer (uma ação principal em destaque), o que vai acontecer (rótulo que diz o resultado, estado sempre visível). Hierarquia por tamanho, contraste e espaço — “se tudo grita, nada é ouvido”. | Em 5 segundos a pessoa diz para que serve a tela e qual é o próximo passo? |
| Objetividade | Uma tela, um objetivo, um CTA primary. Mostre só o que serve à ação do momento; o resto fica atrás de um clique (Collapse, Drawer, Modal). Preencha o que o sistema já sabe. | A ação principal cabe em uma frase sem “e”? |
| Consistência | Mesma coisa, mesma aparência (tokens, nunca valor avulso); mesmo gesto, mesmo resultado (se Excluir confirma numa tela, confirma em todas); um conceito, um nome. Antes de criar, procure no MDS. | Quem domina uma tela adivinha como funciona outra? |
9.2 Filosofia — quando as regras acabam
- O sistema carrega a complexidade, não a pessoa (Lei de Tesler): calcule, valide, preencha, sugira. Não peça digitação do que o sistema já sabe (usuário logado, carga selecionada, data de hoje).
- Projete para o “usuário bêbado” — distraído, com pressa, de luva, no celular no pátio sob o sol, interrompido: alvos de toque generosos, contexto sempre visível, caminho de volta, dados preservados se a pessoa for interrompida, prevenção de erro em vez de só mensagem de erro. (proposta como checklist de revisão)
- A pessoa no controle: preencha automaticamente mas deixe editar; toda ação que altera dado pode ser desfeita ou avisa claramente que não pode; nunca tome decisão irreversível pela pessoa.
- Design não é decoração: sem enfeite que não ajude a tarefa (ilustração no lugar de dado, animação sem função, gradiente que compete com a informação). Cor, espaço e tipografia servem à hierarquia. Beleza é consequência de clareza.
9.3 Estados da interface
Nenhuma tela está pronta enquanto os cinco estados não estiverem desenhados e implementados — o estado “com dados” é só um deles.
| Estado | Pergunta que responde | Componente |
|---|---|---|
| Carregando | O sistema está trabalhando? | .mds-loader, .mds-loader-box, .mds-progress--bar/--circle |
| Vazio | Por que não há nada aqui e o que faço? | .mds-empty-state |
| Erro | O que falhou e como resolvo? | .mds-alert--danger ou EmptyState com ação “Tentar novamente” |
| Sucesso | Deu certo? | Toast (ver lacuna abaixo), .mds-btn--success, tela de conclusão |
| Com dados | Estado principal | O componente da tela |
Carregando
- Nunca deixe o usuário olhando tela parada sem saber se travou. Escopo: global (página inteira → loader centralizado), da área (
.mds-loader-boxsobre o painel/tabela; o resto segue utilizável), inline (botão.mds-btn--loading). - Diga o que carrega, em caixa de sentença e sem pronome: “Gerando relatório…”, “Carregando viagens…” — nunca “Por favor, aguarde enquanto carregamos…”.
- Desabilite a ação em andamento (evita despacho duplo). Prefira barra de progresso a spinner quando o sistema sabe quanto falta.
- Skeleton não existe (nem em CSS nem no Angular): use
.mds-loader-boxsobre a área. Não invente.mds-skeleton.
Vazio
- Estrutura fixa de cima para baixo: ícone/ilustração ligado ao contexto → título (caixa de título) → descrição (por quê/como resolver, caixa de sentença) → ação. Título e descrição são obrigatórios; ilustração sozinha não explica nada; nunca “Ops, nada por aqui”.
- Três vazios diferentes: primeiro uso (ação = criar: “Subir Arquivo”), sem resultado do filtro (ação = Limpar Filtros, não criar), tudo em ordem (“Nenhum Alerta Pendente” + “Ir para o Dashboard”).
Erro
- Três escalas: campo (no campo, abaixo dele), ação (Alert no contexto, ou Toast se não exigir correção), tela (estado de erro ocupando a área, com “Tentar novamente” — proposta).
- Fórmula: o que aconteceu + como resolver, sem culpa — “CPF inválido. Insira apenas números.”, nunca “Você digitou o CPF errado.” / “Ocorreu um erro.”
- Preserve tudo que o usuário digitou. Mantenha o erro visível até ser resolvido. Erro de campo aparece ao sair do campo, não a cada tecla.
Sucesso
- Proporcional ao impacto: ação pequena → Toast “Alterações salvas.”; conclusão de fluxo (despachar, registrar entrega) → botão Success + estado de conclusão; ação em massa → resumo completo “12 cargas despachadas. 2 com falha.”
9.4 Feedback ao usuário
Regra de ouro: o peso do feedback é proporcional ao impacto — quanto mais a pessoa precisa agir, mais ele interrompe e permanece visível. Um erro que some sozinho em 4 s pode ser uma carga não despachada que ninguém viu.
Escolha o componente respondendo na ordem e parando no primeiro “sim”:
- Mensagem sobre um campo de formulário? → mensagem no próprio campo (
.mds-input--danger+.mds-input__helper). - Precisa de decisão antes de continuar (confirmar exclusão, escolher)? → Modal (
.mds-float-panel--modal). - O problema precisa continuar visível até ser resolvido (falha na emissão, manutenção atrasada)? → Alert (
.mds-alert--{neutral|info|warning|danger|success}). - Só confirma o resultado de uma ação, sem nada a fazer? → Toast.
- Explicação curta de ícone/sigla/dado? → Tooltip (
.mds-tooltip). - Não há dados? → EmptyState.
| Tipo (Alert) | Cor | Quando usar |
|---|---|---|
| Erro | Danger (vermelho) | Bloqueia a operação — falha na emissão de nota |
| Aviso | Warning (amarelo) | Requer cautela, não bloqueia — veículo com manutenção atrasada |
| Sucesso | Success (verde) | Confirma conclusão — rota otimizada |
| Informação | Info (azul) | Contexto útil, sem urgência — nova versão do manifesto disponível |
| Neutro | sem cor semântica | Aviso genérico, sem peso semântico |
- A cor nunca é o único sinal: acompanhe sempre com texto e, quando couber, ícone (parte dos operadores não distingue vermelho de verde; o sol no pátio apaga contraste sutil). Vermelho é reservado para erro — para destacar “importante”, use aviso.
- Alert: fica no contexto do problema (topo da área afetada, não num canto distante); dispensável só quando ignorar não tem consequência; um por área (vários problemas → uma lista dentro de um Alert). Botão de ação que leva a tela de resolução usa reticências (“Configurar impressora…”).
- Toast: no máximo uma frase curta, sem ação crítica, sem tirar o foco; nunca o único registro de erro que exige correção. (proposta) sucesso/info somem sozinhos, erro permanece até ser dispensado; um por vez, o resto em fila.
- Modal: só para interromper (confirmação crítica, decisão, detalhe que pede foco total); sempre com saída clara (Cancelar e ×); nunca abra modal sobre modal — fluxo longo usa Drawer. (proposta) foco preso dentro, Esc fecha, foco volta ao elemento de origem.
- Tooltip: descreve ícone sem texto visível; nunca repete o rótulo visível; nunca carrega informação essencial ou ação (não aparece em toque); sem ponto final.
- Lacuna conhecida — Toast: existe só no Figma; não há
.mds-toastnem<mds-toast>. A aproximação prevista é<mds-alert [fixed]="true" [dismissible]="true">(.mds-alertfixo e dispensável). Não invente a classe; sinalize no ticket que a tela usa a aproximação.
9.5 Ações destrutivas e confirmação
Regra de ouro: o atrito da confirmação é proporcional ao custo de desfazer. Reversível → sem confirmar. Irreversível → confirmação explícita dizendo o que será perdido. Confirmar tudo faz o operador clicar “OK” sem ler.
| Nível de atrito | Quando | O que fazer |
|---|---|---|
| 1. Reversível, baixo impacto | Recuperável fácil, afeta só o próprio usuário | Executa direto + Toast. (proposta) oferecer “Desfazer” por alguns segundos |
| 2. Destrutivo e limitado | Apaga/cancela um item; perda grande mas isolada (excluir rota, cancelar agendamento) | Modal de confirmação |
| 3. Irreversível, em massa ou com impacto em outros | Não recupera, ou afeta muitos itens/pessoas | Modal com a consequência explícita; (proposta) nos casos graves, exigir digitar o nome/número do item |
Anatomia da modal de confirmação (sempre estas partes):
- Título: a pergunta com ação + objeto, caixa de título, termina em “?” → Excluir Rota?
- Corpo: o que será perdido, com números e nomes, e se dá para desfazer; cite impacto em outras pessoas quando houver → “A rota RT-2041 e seus 12 pontos de parada serão removidos. Essa ação não pode ser desfeita.”
- Saída: Cancelar, estilo secundário. Confirmação: repete a ação,
.mds-btn--danger→ Excluir Rota. Nunca “Sim”/“Não”/“OK”; sem reticências no botão de confirmação.
- Fechar (×, Esc, clique no backdrop) equivale a Cancelar — nunca confirma. Uma decisão por modal. Sem tom de ameaça, caixa alta ou exclamação: a seriedade vem do conteúdo. (proposta) foco inicial em Cancelar, para Enter sem pensar não destruir nada.
- Vocabulário: Excluir = apaga de forma definitiva; Cancelar = interrompe algo em andamento/criado e mantém histórico; Remover = tira da lista/vínculo sem apagar o item (verbo ainda a validar com Produto). Não misture os três.
- Prefira alternativas a excluir quando há histórico/auditoria/obrigação fiscal: motorista com viagens → Inativar Motorista (proposta); carga que já andou → Cancelar Carga; documento fiscal emitido → não oferecer exclusão, emitir o cancelamento/correção previsto em lei.
- Posição na tela: a ação destrutiva nunca é o primary da tela; usa Danger e peso visual menor que a principal. Em menu de ações: no fim, separada por divisor, em cor de perigo; frequentes (Editar, Duplicar) no topo. Em linha de tabela: uma ação → botão de ícone com Tooltip; duas ou mais → menu Mais opções com a destrutiva no fim. Afaste de ações de uso constante (toque/luva). O item de menu que abre a confirmação leva reticências (“Excluir Registro…”).
- Em massa: selecionar não executa (ação em botão separado); a confirmação diz a quantidade (“Excluir 12 cargas?”); diga antes quais itens não podem ser afetados e por quê; depois mostre o resultado completo (“10 cargas excluídas. 2 mantidas.”) — nunca só “Concluído”.
- Prevenir em vez de confirmar: ação inválida fica desabilitada com Tooltip explicando o motivo (“Carga em trânsito. Cancele a viagem para excluir.”); bloqueie por dependência e explique; respeite permissões (sem permissão, não aparece ou desabilita com motivo); mostre o impacto antes do clique.
- Depois: sucesso → Toast “Rota excluída.” e o item some da lista imediatamente, usuário continua onde estava (volta à lista, não a uma tela vazia); falha → Alert no contexto, item continua na lista; parcial → resumo do que foi e do que falhou, com motivo.
9.6 Formulários e validação
Regra de ouro: só peça o que é necessário para concluir a tarefa agora; o resto pode ser preenchido depois. Antes de desenhar cada campo: o sistema já sabe? precisa agora? dá para escolher em vez de digitar?
- Uma coluna por padrão; duas só para campos curtos e relacionados (CEP + número; data + hora). Rótulo sempre acima e visível — placeholder nunca substitui rótulo. Texto de apoio abaixo, curto, esmaecido; explica formato ou consequência, não repete o rótulo.
- Ordem da tarefa, não do banco de dados. Agrupe campos relacionados sob cabeçalho de seção (SectionHeader: “Dados do motorista”, “Veículo”). Revelação progressiva: campos dependentes só aparecem depois da escolha (ConfigToggle, opção “Outro”). (proposta) acima de ~10 campos, use seções/etapas com indicação do que falta.
- Obrigatório: realce amarelo (warning) + asterisco no rótulo +
aria-required="true"(.mds-input--required); vermelho é só erro. Explique o asterisco no topo se houver mais de um. (proposta) se quase tudo é obrigatório, marque os opcionais com “(opcional)” e retire o amarelo.
Qual controle usar
| Necessidade | Controle | Regra |
|---|---|---|
| Texto, número, dado com máscara (CPF, CNPJ, CEP, placa, moeda) | Input | Use a máscara pronta do tipo, nunca máscara customizada |
| Uma opção entre 2 a 5 | Radio | Sempre com uma opção pré-selecionada e título de grupo |
| Uma ou mais entre muitas | Select com busca | Múltipla mostra tags dentro do campo (só via Angular) |
| Marcar itens de uma lista | Checkbox | Cada caixa independente; só vale após confirmar |
| Ligar/desligar com efeito imediato | Switch | Sem botão de confirmar. Se só vale após “Salvar” → Checkbox |
| Ligar/desligar um bloco de campos | ConfigToggle | Campos dependentes aparecem logo abaixo |
| Data ou período | DatePicker | dd/mm/aaaa, com atalhos (Hoje, Últimos 7 dias) |
| Arquivo | Uploader | Mostre formatos e tamanho aceitos antes do envio (só via Angular) |
| Cadastrar item que falta num Select | MicroForm (.mds-microform) |
Máx. 5 campos; o que foi digitado na busca entra no campo principal; ao confirmar, o item já fica selecionado |
- Input/Select/DatePicker: substantivo curto, caixa de sentença. Checkbox: positivo e diz o que acontece ao marcar (“Incluir seguro de carga”, não “Não deixar sem seguro”). Switch: rótulo estático, nunca alterna entre “Ativado/Desativado”, sem pergunta (“Rastreador GPS”). ConfigToggle: título em caixa de título + descrição em sentença. Placeholder de Select convida sem reticências (“Selecione o estado”).
Prevenção
- Prefira prevenir: máscaras para dados formatados; restrinja o que não faz sentido (datas retroativas em agendamento futuro; campo dependente desabilitado até a origem ser preenchida); valores padrão inteligentes; placeholder com formato quando a máscara não deixa claro (ABC-1234, 00.000-000); busca no Select em listas longas. Nunca bloqueie a digitação por regra de validação — o campo não “engole” o que a pessoa digita.
Quando validar
| Momento | Regra |
|---|---|
| Enquanto digita | Não mostra erro (exceção: requisito que se cumpre em tempo real, como força de senha) |
| Ao sair do campo | Valida e mostra o erro daquele campo |
| Ao enviar | Valida tudo; (proposta) foco no primeiro campo com erro e resumo se houver mais de um |
| Depois de corrigir | O erro some assim que o valor fica válido |
- Mensagem = o que está errado + como corrigir, no próprio campo, abaixo dele, em vermelho, sem culpa. Nunca “inválido” sozinho: “Informe a placa do veículo.”, “CPF inválido. Insira apenas números.”, “Mínimo de 8 caracteres.”, “Já existe um motorista com este CPF.”, “O peso máximo por carga é 32.000 kg.”.
- Erro do servidor: de um campo → no campo, com foco nele; do envio como um todo (falha de conexão) → Alert no topo do formulário (“Falha ao salvar a carga CG-1042. Verifique a conexão e tente novamente.”). Nos dois casos mantenha os dados e devolva o botão ao estado normal para nova tentativa.
Ações do formulário
- Um único botão primary com o verbo da tarefa (Salvar, Emitir Nota, Agendar Doca); Cancelar ao lado em estilo secundário, nunca mais chamativo que o de salvar. Botões fixos no rodapé do Drawer/Modal. Enquanto envia: botão em carregamento (“Salvando…”) e inerte (sem envio duplo).
- Não desabilite o enviar só porque o formulário está inválido sem explicar (proposta: deixe clicar e mostre os erros). (proposta) Com alterações não salvas, confirme antes de sair: Descartar alterações? → Continuar Editando · Descartar.
| Situação | Onde colocar | Por quê |
|---|---|---|
| Cadastro/edição completa | Drawer (.mds-float-panel--drawer) |
Mantém tabela/mapa visível ao fundo, preservando o contexto |
| Poucos campos e uma decisão | Modal (.mds-float-panel--modal) |
Foco total; a pessoa volta logo |
| Item que falta em um Select | MicroForm | Cadastra sem sair do fluxo |
| Configuração de recurso | ConfigToggle na própria tela | Campos só aparecem quando o recurso é ligado |
Estados de campo
| Estado | Como se apresenta |
|---|---|
| Padrão | Borda neutra, fundo surface; placeholder só exemplifica formato, sem reticências |
| Foco | Borda realçada em primary; rótulo ganha destaque |
| Obrigatório | Realce amarelo + asterisco + aria-required (.mds-input--required) |
| Preenchido | Borda de maior peso visual (.mds-input--active) — confirma que o dado foi assimilado |
| Desabilitado | Opacidade reduzida, cursor de bloqueio; rótulo legível; (proposta) explique o motivo em tooltip/apoio |
| Somente leitura | Fundo e texto esmaecidos, valor visível |
| Erro | Borda e mensagem em vermelho (.mds-input--danger), mensagem específica |
Acessibilidade
- Rótulo associado ao campo (clicar no texto foca; em Radio/Checkbox, marca). Erro nunca só por cor (texto + ícone/borda). Ordem de tabulação = ordem visual. Alvo de toque confortável para luva/tablet. (proposta) mensagem de erro ligada ao campo com
aria-describedby.
9.7 Navegação e hierarquia
Regra de ouro: cada tipo de navegação tem um lugar e um componente; não misture (páginas de módulos diferentes no mesmo submenu, ação no lugar de destino, produto dentro do menu do módulo). A pessoa sempre sabe onde está, o que pode fazer e como chegar a outro lugar.
Hierarquia, do mais amplo ao detalhe: Produto (AppLauncher) → Contexto/unidade (.mds-menu-business) → Módulo (menu nível 1) → Página (menu nível 2) → Aba → Seção (SectionHeader).
| Preciso… | Use |
|---|---|
| Trocar de produto (TMS, Roteirizador, Torre de Controle) | AppLauncher na topbar (produtos não licenciados separados) |
| Trocar de unidade/empresa | Alternador de contexto .mds-menu-business (muda dados, permissões, módulos) |
| Outro módulo | Menu lateral, nível 1 (.mds-menu + .mds-menu-item) |
| Outra página do módulo | Menu lateral, nível 2 (.mds-menu__group, item --sm) |
| Outro conteúdo da mesma página | Tabs (.mds-nav-tabs); subpágina tem rota própria |
| 2–3 visões exclusivas simples, sem rota | .mds-control-group |
| Subir um nível | Breadcrumb (.mds-breadcrumbs) |
| Executar algo | Botão ou Dropdown — ação não é destino |
| Dividir a página em blocos | SectionHeader (só Angular, header[mdsSectionHeader]) |
| Escolher período | DateNavigator (disponibilidade) ou DatePicker (dado) |
- Máximo de dois níveis no menu (módulo › página) e no Dropdown (menu › submenu). Se sente falta de um terceiro, o problema é a estrutura da informação: reagrupe, use Tabs ou outro módulo. Nunca aninhe mais.
- Menu lateral: nível 1 = módulo, com ícone e maior peso; nível 2 = só páginas daquele módulo, menores e recuados. Rótulos em caixa de título, curtos (“Dashboard”, não “Ver o Dashboard de indicadores”). Item ativo sempre destacado (fundo claro de
primary,.mds-menu-item--active); módulo com página ativa abre sozinho. Navegação utilitária (Automação, Preferências, Integrações, Cadastros gerais) ancorada na base, separada dos módulos operacionais. - Três modos do menu: expandido (256 px, ícone + rótulo), compacto (64 px, só ícones com Tooltip em cada um), flutuante (mobile/telas reduzidas, sobrepõe o conteúdo,
.mds-menu--floating). - Topbar (
.mds-top-bar, 64 px, fixa e visível em todas as telas): marca + nome do produto ativo à esquerda; pesquisa global (cargas, veículos, motoristas); utilitários (notificações, ajuda, seletor de produtos, perfil) — (proposta) em ordem fixa, do mais ao menos frequente. Botão só-ícone sempre com Tooltip. Um único lugar para trocar a unidade (o perfil pode mostrá-la, não trocá-la). - Breadcrumb só em páginas com 3+ níveis (em estrutura plana, não use). Último item = página atual, sem link; anteriores são links; nomes curtos; a partir de 4 itens colapsa o meio em “…” (caractere único).
- PageHeader (
.mds-page-title+.mds-page-options): um título por página, caixa de título, igual ao item de menu; ação principal (primary, verbo) junto ao título — um único destaque por tela; utilitários à direita (atualizar ↻, filtros/configurações, Mais opções ⋮) só ícone com Tooltip; busca rápida com placeholder “Pesquisar por código” (Pesquisar, nunca “Buscar”). - Tabs: só conteúdos do mesmo nível (nunca trocar módulo/produto); rótulos substantivos em caixa de título, sem ponto; a mais importante à esquerda; exatamente uma ativa; ícone em todas ou em nenhuma; modo compacto só-ícone exige Tooltip (aba sem ícone precisa manter o rótulo).
- SectionHeader: título em caixa de título, descrição opcional em sentença; tamanho reflete a profundidade (seção mestra > subseção); se uma seção tem descrição, todas têm. Dropdown: item pai curto e categórico, seta para submenu sem reticências; frequentes no topo, destrutivas no fim separadas por divisor em
danger; item que abre confirmação/janela leva reticências. - Localização e estado: item de menu ativo, aba ativa e último item do breadcrumb dizem a mesma coisa. (proposta) URL é o estado (módulo/página/aba na URL; link compartilhável; voltar do navegador funciona). Item sem permissão não aparece (ou aparece desabilitado com o motivo). Ao carregar a próxima página, menu e cabeçalho ficam no lugar; só a área de conteúdo carrega.
- Nome de destino é substantivo, nome de ação é verbo (“Agendamentos” leva a uma lista; “Novo Agendamento” faz algo) — não misture no mesmo menu. Título da página = item de menu = (versão curta no) breadcrumb.
Hierarquia visual na página
- Uma ação principal por tela, junto ao título; as demais secundárias ou em Mais opções. Ordem de leitura = importância (mais crítico primeiro, à esquerda e no topo). Um título, muitos subtítulos — não pule níveis. Peso visual proporcional à importância (módulo > página; seção mestra > subseção).
- Ícones ajudam, não substituem texto na navegação principal; ícone sozinho só em modo compacto, sempre com Tooltip.
9.8 Checklist de revisão (auto-verificação antes de entregar)
- Sei dizer o problema real que a tela resolve, sua ação principal em uma frase e há no máximo um botão primary?
- Os cinco estados (carregando, vazio, erro, sucesso, com dados) estão contemplados? O carregamento diz o quê; o vazio tem título + descrição + ação?
- Escolhi o componente de feedback pela árvore de decisão (campo → Modal → Alert → Toast → Tooltip → EmptyState)? Erro que exige ação não depende só de Toast? Nada depende só de cor?
- Ação destrutiva: atrito proporcional, confirmação com título-pergunta + botão que repete a ação (Danger) + Cancelar, nunca “Sim/OK”?
- Formulário: uma coluna, rótulo visível acima, máscara/tipo certo, validação ao sair do campo, mensagem “o que + como corrigir”, dados preservados em erro, envio com botão inerte em carregamento?
- Navegação: no máximo dois níveis, título = item de menu, item ativo/aba/breadcrumb concordam, botão só-ícone com Tooltip, substantivo para destino e verbo para ação?
- Usei só componentes, tokens e classes existentes (nada de
.mds-toast/.mds-skeleton/estilo local “quase igual”)? Se abri exceção, sei justificar?
Este arquivo é regenerado por npm run design:build (ver package.json). O gerador falha (em vez de gerar algo errado) se um valor que ele espera encontrar no SCSS mudou de lugar — rode npm run design:build de novo para ver a mensagem de erro com o arquivo/linha exatos.