Pular para o conteúdo

Estados da interface

Toda tela que mostra dados existe em mais de um estado. O desenho “feliz”, com dados carregados, é só um deles. Na operação logística, os outros estados são os que a pessoa mais vê: a conexão do pátio oscila, o filtro não retorna nada, o servidor demora. Regra de ouro: nenhuma tela está pronta enquanto os cinco estados abaixo não estiverem desenhados e implementados.

Estado Pergunta que responde Componente
Carregando “O sistema está trabalhando?” Loader, Progress
Vazio “Por que não há nada aqui e o que faço?” EmptyState
Erro “O que falhou e como resolvo?” Alert ou EmptyState com ação de tentar de novo
Sucesso “Deu certo?” Toast, botão Success, tela de conclusão
Com dados O estado principal O componente da tela

Regra: o usuário nunca fica olhando uma tela parada sem saber se o sistema travou.

Escopo Quando Como
Global Página inteira carregando Loader centralizado
Da área Painel, tabela ou card carregando Loader sobre a área afetada (o resto da tela continua utilizável)
Inline Uma ação específica, como salvar Botão em estado de carregamento
Skeleton Antecipar a estrutura de tabelas e painéis Ainda sem componente (veja Para desenvolvedores)
  • Deve dizer o que está sendo carregado, sempre que possível: Gerando relatório…, Pesquisando motoristas…, Salvando…
  • Deve usar caixa de sentença, sem pronomes nem artigos. “Por favor, aguarde enquanto carregamos…” vira Carregando…
  • Reticências: use quando a espera for longa (espera ativa). Em spinners pequenos dentro de botões, são opcionais.
  • Deve desabilitar a ação que está em andamento para evitar duplo clique (duas cargas despachadas por engano é um problema real).
  • Recomendado usar barra de progresso, em vez de spinner, quando o sistema sabe quanto falta (importação de arquivo, geração de relatório longo).
  • [Proposta] Referência de tempos de resposta (Nielsen): até ~1 s não precisa de indicador; entre 1 e 10 s use spinner; acima de 10 s mostre progresso e permita continuar em outra tela.

O EmptyState transforma uma tela vazia em um próximo passo. Existem dois vazios diferentes, e a mensagem muda:

Tipo Situação Título Descrição Ação
Primeiro uso Nunca houve dado Nenhum Documento O veículo ainda não possui anexos cadastrados. Subir Arquivo
Sem resultado Há dado, mas o filtro escondeu tudo Motorista Não Encontrado Nenhum motorista com o CPF informado. Limpar Filtros
Tudo em ordem Ausência é boa notícia Nenhum Alerta Pendente Não há alertas para ler no momento. Ir para o Dashboard
Estrutura, de cima para baixo:
  1. Ícone ou ilustração ligado ao contexto (uma caixa para “sem mercadoria”).
  2. Título: o que está acontecendo, em Caixa de Título.
  3. Descrição: por que e como resolver, em caixa de sentença.
  4. Ação: um caminho para criar o dado ou desfazer o filtro, em Caixa de Título.
  • Deve ter título e descrição. Só ilustração não explica nada.
  • Não deve usar mensagens genéricas (“Ops, nada por aqui”).
  • Recomendado que o vazio de “sem resultado” traga a ação de limpar filtros, não a de criar.

Erros acontecem em três escalas, e cada uma tem seu lugar:

Escala Exemplo Onde aparece
Campo CPF inválido No próprio campo, abaixo dele
Ação Não foi possível salvar a carga Alert no contexto (ou Toast, se não exigir correção)
Tela Não foi possível carregar as viagens Estado de erro ocupando a área, com ação de tentar de novo
Fórmula da mensagem: o que aconteceu + como resolver, sem culpa.
Evite Prefira
— —
Você digitou o CPF errado. CPF inválido. Insira apenas números.
Ocorreu um erro. Falha na conexão. Tente novamente.
Ops, algo deu errado! Não foi possível salvar a carga. Verifique o peso informado.
  • Deve preservar o que o usuário já digitou. Perder um formulário longo por um erro de rede é a pior experiência possível.
  • Deve manter o erro visível até ser resolvido (veja Feedback ao usuário).
  • Recomendado que erros de campo apareçam ao sair do campo, não a cada tecla digitada.
  • [Proposta] Em erro de tela, oferecer sempre Tentar novamente.

Proporcional ao impacto:

Impacto Como confirmar
Ação pequena (salvar, editar) Toast: Alterações salvas.
Conclusão de fluxo (despachar, registrar entrega) Botão Success no fechamento e estado de conclusão claro
Ação em massa Resumo do que foi feito: 12 cargas despachadas. 2 com falha.

Definidos na página do Input e válidos para os campos do sistema:

Estado Como se apresenta Observação
Padrão Borda neutra, fundo padrão Placeholder só exemplifica o formato, sem reticências
Foco Borda realçada na cor primária, com cursor O rótulo ganha destaque
Obrigatório Realce em amarelo, asterisco no rótulo e aria-required Amarelo comunica prioridade sem a conotação punitiva do vermelho
Preenchido Borda de maior peso visual Confirma que o dado foi assimilado
Desabilitado Opacidade reduzida e cursor de bloqueio Rótulo continua legível; evite ajuda longa
Somente leitura Fundo e texto esmaecidos, valor visível Dado que existe, mas não pode ser alterado nesta etapa
Erro Borda e mensagem em vermelho Mensagem específica, veja Erro acima
  • Deve manter o rótulo visível em todos os estados. Placeholder nunca substitui rótulo.
  • [Proposta] Quando um campo ou botão está desabilitado, explique por quê (tooltip ou texto de apoio). Sem isso, a pessoa não sabe o que fazer para habilitar.
Estado Frame no Figma
Loading Loading
EmptyState EmptyState
Input (estados de campo) Input
Ao entregar uma tela, entregue os cinco estados no Figma. Uma tela só com o estado “com dados” está incompleta para desenvolvimento.
Necessidade mds-styles (HTML/CSS) mds-angular Situação
Spinner .mds-loader <mds-loader> Disponível
Carregando sobre uma área .mds-loader-box (--absolute, --full, --lighter) <mds-loader-box> Disponível
Botão carregando .mds-btn mdsButton com [loading] Disponível
Barra e círculo de progresso .mds-progress--bar, .mds-progress--circle <mds-progress-circle> Disponível
Estado vazio .mds-empty-state <mds-empty-state> Disponível
Erro em campo .mds-input--danger <mds-input> Disponível
Skeleton não existe não existe Lacuna

Lacuna conhecida: Skeleton. A página do Loading prevê skeleton para antecipar tabelas e painéis, mas não há componente dedicado no mds-styles nem no mds-angular. Até existir, use .mds-loader-box sobre a área.

  • A tela tem os cinco estados desenhados e implementados?
  • O carregamento diz o que está sendo carregado?
  • A ação em andamento está desabilitada para evitar duplo envio?
  • O vazio tem título, descrição e ação, e distingue “primeiro uso” de “sem resultado”?
  • A mensagem de erro diz o que aconteceu e como resolver, sem culpa?
  • O que o usuário digitou é preservado quando há erro?
  • Campos desabilitados mantêm o rótulo e explicam o motivo?