Pular para o conteúdo

Formulários e validação

Formulário é o trabalho de quem opera o sistema: cadastrar motorista, agendar doca, emitir nota. Cada campo a mais custa tempo e cada erro custa retrabalho. Um bom formulário logístico pede só o necessário, na ordem em que a pessoa pensa, e avisa do erro antes de ela perder o que digitou. Regra de ouro: só peça o que é necessário para concluir a tarefa agora. Todo o resto pode ser preenchido depois.

  1. Precisa mesmo deste campo? Se o sistema já sabe (usuário logado, carga selecionada, data de hoje), preencha sozinho.
  2. Precisa agora? Dado que só importa depois vai para uma etapa posterior ou para “editar”.
  3. Dá para escolher em vez de digitar? Select, Radio e DatePicker erram menos que texto livre.
  • Uma coluna por padrão. Duas colunas só para campos curtos e relacionados (CEP e número; data e hora).
  • Rótulo sempre acima do campo, visível. O placeholder nunca substitui o rótulo.
  • Ordem que segue a tarefa, não o banco de dados: a mesma ordem do documento ou do processo que a pessoa já conhece.
  • Agrupe campos relacionados sob um cabeçalho de seção (SectionHeader): “Dados do motorista”, “Veículo”, “Endereço de coleta”.
  • Texto de apoio abaixo do campo, curto, em cor esmaecida. Explica formato ou consequência, não repete o rótulo.
  • Revelação progressiva: campos que só fazem sentido depois de uma escolha aparecem quando a escolha é feita (ConfigToggle, opção “Outro”).
  • [Proposta] Formulário longo (mais de ~10 campos) pede seções ou etapas, e indicação clara do que falta.
  • Campo obrigatório: **realce em amarelo, asterisco () ao lado do rótulo e aria-required="true". O amarelo vira guia de varredura em formulários longos; vermelho fica reservado para erro.
  • Deve mostrar ao usuário, no topo do formulário, o que o asterisco significa, se houver mais de um campo obrigatório.
  • [Proposta] Quando quase todos os campos são obrigatórios, marque os opcionais com “(opcional)” e retire o realce amarelo. Marcar a exceção reduz ruído.
Necessidade Controle Regra
Texto, número, dado com máscara (CPF, CNPJ, CEP, placa, moeda) Input Use a máscara pronta do tipo, não uma máscara customizada
Uma opção entre 2 a 5 Radio Button Sempre com uma opção pré-selecionada e um título de grupo
Uma ou mais opções entre muitas Select (com busca) Seleção múltipla mostra tags dentro do campo
Marcar um ou mais itens de uma lista Checkbox Cada caixa é independente; a ação só vale após confirmar
Ligar/desligar com efeito imediato Switch Sem botão de confirmação depois
Ligar/desligar um bloco de campos ConfigToggle Os campos dependentes aparecem logo abaixo
Data ou período DatePicker Formato DD/MM/AAAA, com atalhos (Hoje, Últimos 7 dias)
Arquivo Uploader Mostre formatos e tamanho aceitos antes do envio
Cadastro rápido de um item que falta em um Select MicroForm No máximo 5 campos
Checkbox ou Switch? Se a mudança só vale depois de clicar em “Salvar”, é Checkbox. Se vale na hora, é Switch.
Controle Regra Exemplo
Input, Select, DatePicker Substantivo curto, caixa de sentença Data de embarque · Cidade de destino
Checkbox Positivo e diz o que acontece ao marcar Incluir seguro de carga (não “Não deixar sem seguro”)
Radio Título do grupo + opções curtas e positivas Grupo Tipo de frete: Carga fechada · Fracionada
Switch Estático (nunca troca entre “Ativado” e “Desativado”) e sem pergunta Rastreador GPS (não “Você deseja ativar o GPS?”)
ConfigToggle Título em caixa de título + descrição de apoio em caixa de sentença Alerta de Atraso · Destacar cargas com mais de 2 horas de atraso.
Select (placeholder) Convida a interagir, sem reticências Pesquisar transportadora · Selecione o estado
Uploader Instrução curta + botão em caixa de título Arraste os arquivos aqui · Selecione os Arquivos

O melhor erro é o que não acontece:

  • Máscaras para dados formatados (documento, telefone, CEP, placa, moeda).
  • Restrinja o que não faz sentido: datas retroativas em agendamento futuro, campo dependente desabilitado até o campo de origem ser preenchido.
  • Valores padrão inteligentes (data de hoje, unidade mais usada).
  • Placeholder com formato quando a máscara não deixa claro: ABC-1234, 00.000-000.
  • Busca no Select em listas longas, em vez de rolagem.
  • Nunca bloqueie a digitação por regra de validação (o campo não pode “engolir” o que a pessoa digita).
Momento Regra
Enquanto digita Não mostrar erro. Exceção: requisito que se cumpre em tempo real, como a força de senha, que vai sendo riscado
Ao sair do campo Valida e mostra o erro daquele campo
Ao enviar Valida tudo; [Proposta] leva o foco ao primeiro campo com erro e mostra um resumo se houver mais de um
Depois de corrigir O erro some assim que o valor fica válido

Fórmula: o que está errado + como corrigir, no próprio campo, abaixo dele, em vermelho, sem culpa.

Situação Evite Prefira
Obrigatório vazio Campo obrigatório Informe a placa do veículo.
Formato inválido Valor inválido CPF inválido. Insira apenas números.
CNPJ incompleto Campo inválido Informe um CNPJ com 14 dígitos.
Tamanho mínimo O campo deve possuir no mínimo 8 caracteres Mínimo de 8 caracteres.
Tamanho máximo O campo deve possuir no máximo 50 caracteres Máximo de 50 caracteres.
E-mail E-mail inválido Informe um e-mail válido. Ex: nome@empresa.com.br
Duplicado Erro Já existe um motorista com este CPF.
Dependência entre campos Data inválida A data de saída deve ser anterior à data de chegada.
Fora da faixa Valor incorreto O peso máximo por carga é 32.000 kg.
  • Deve dizer qual é o problema. “Inválido” sozinho não ajuda.
  • Não deve culpar: “Você digitou errado”, “Ops”.
  • Deve preservar tudo que a pessoa já preencheu.

Falhou depois do envio (documento rejeitado, conflito de agenda, sem conexão)?

  • Se o erro é de um campo (CPF já cadastrado), mostre no campo, e leve o foco a ele.
  • Se é do envio como um todo (falha na conexão, serviço indisponível), mostre um 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 o botão volta ao estado normal para permitir nova tentativa.
  • Um único botão de destaque (primary), com o verbo da tarefa: Salvar, Emitir Nota, Agendar Doca.
  • Cancelar ao lado, com estilo secundário. Ele nunca deve parecer mais importante que o de salvar.
  • Botões fixos no rodapé do Drawer ou da Modal, para ficarem sempre à vista.
  • Enquanto envia, o botão entra em carregamento (Salvando…) e fica inerte, para evitar envio duplo.
  • Não desabilite o botão de enviar por o formulário estar inválido sem explicar. [Proposta] Deixe clicar e mostre os erros; um botão cinza sem motivo deixa a pessoa sem saída.
  • [Proposta] Se há alterações não salvas, confirme antes de sair: Descartar alterações? com Continuar Editando · Descartar.
Situação Onde Por quê
Cadastro ou edição completa Drawer (painel lateral) Mantém a tabela ou o mapa visível ao fundo, preservando o contexto
Poucos campos e uma decisão Modal Foco total, e a pessoa volta logo
Item que falta em um Select MicroForm Cadastra sem sair do fluxo, e o item novo já vem selecionado
Configuração de recurso ConfigToggle na própria tela Os campos aparecem só quando o recurso é ligado
  • Aparece no fim da lista do Select quando a busca não acha o item: Adicionar “Transportadora Alfa”…
  • O que a pessoa digitou na busca entra automaticamente no campo principal do MicroForm (ex: Razão Social).
  • No máximo 5 campos, só os indispensáveis. O texto de ajuda avisa que o resto pode ser completado depois.
  • Ao confirmar, ele fecha e o item novo já fica selecionado no campo de origem. Botões: Cancelar · Adicionar.
  • Rótulo associado ao campo (clicar no texto foca o campo; nos Radios e Checkboxes, clicar no texto também marca, o que ajuda em tablet de armazém).
  • Erro nunca depende só de cor: texto explicando, mais o ícone ou a borda.
  • Campo obrigatório: asterisco e aria-required, além do amarelo.
  • [Proposta] A mensagem de erro é ligada ao campo (aria-describedby) e anunciada por leitores de tela.
  • Ordem de tabulação segue a ordem visual.
  • Alvo de toque confortável para uso com luva e em tablet.
Controle Frame no Figma
Input Input
Select Select / Autocomplete
Checkbox e Radio Checkbox / Radio
Switch Toggle / Switch
ConfigToggle ConfigToggle
MicroForm MicroForm
Uploader Uploader
Cabeçalho de seção SectionHeader
DatePicker Sem frame no Notion ainda
Entregue cada campo com todos os estados (padrão, foco, preenchido, obrigatório, desabilitado, somente leitura, erro) e o formulário com erro de envio.
Controle mds-styles (HTML/CSS) mds-angular
Input .mds-input > __field + __label + __helper; --required, --danger <mds-input [label] [required] [help] [variant]>
Select Só via Angular <mds-select [placeholder] [multiple] [notFoundText]>
Checkbox / Switch .form-check (checkbox) <mds-checkbox [label] [mode]>
Radio .form-check <mds-radio>
MicroForm .mds-microform <mds-microform [label] [help]>
Uploader Só via Angular <mds-anexo-upload [multiple] [supportedFileTypes]>
  • No mds-input, required aplica o realce amarelo e o asterisco, help é o texto de apoio, e **msgErrorRequired****, msgErrorMask, msgErrorMinLength, msgErrorMaxLength, **msgErrorEmail trocam as mensagens de erro. Sempre personalize as mensagens do campo, para dizer qual é o campo e como corrigir.
  • Use o type com máscara pronta (cpf, cnpj, cep, money…) em vez de customMask.

Mensagens padrão do código que divergem destas diretrizes

Seção intitulada “Mensagens padrão do código que divergem destas diretrizes”

O que vem de fábrica no mds-angular ainda não segue o Estilo de escrita. Até alinhar, personalize nos formulários ou ajuste o padrão na biblioteca:

Componente Padrão atual Sugestão
mds-input (msgErrorMask) Valor inválido Genérica demais. Exigir mensagem por tipo de campo
mds-input (msgErrorMinLength) O campo deve possuir no mínimo N caracteres Mínimo de N caracteres.
mds-input (msgErrorMaxLength) O campo deve possuir no máximo N caracteres Máximo de N caracteres.
mds-input (msgErrorRequired) Campo obrigatório Aceitável como padrão; melhor com o nome do campo: Informe a placa do veículo.
mds-input (msgErrorEmail) E-mail inválido Informe um e-mail válido. Ex: nome@empresa.com.br
mds-select (loadingText) Pesquisando… Pesquisando… (caractere único de reticências)
mds-select (notFoundText) Nenhum item encontrado Nenhum resultado encontrado. (é o texto do Notion para o Select)
  • Cada campo é necessário agora? O que o sistema já sabe está preenchido?
  • Rótulo visível acima de todo campo, e placeholder só mostra formato?
  • Obrigatórios marcados com realce, asterisco e aria-required?
  • Controle certo (Radio para 2–5, Select para muitos, Switch só com efeito imediato)?
  • Máscaras e restrições evitam o erro antes de ele acontecer?
  • Erro aparece ao sair do campo, diz o que corrigir e não culpa?
  • Erro de envio aparece em um Alert, com os dados preservados?
  • Um único botão de destaque, com verbo específico, e ele entra em carregamento ao enviar?
  • Formulário de cadastro em Drawer; MicroForm com no máximo 5 campos?
  • Os estados de campo, o erro de envio e o estado vazio estão desenhados?