Aprenda / UI/UX para quem programa

FundamentosAula 8 de 1614 min0% da trilha

Estados e feedback visual

Um botão que não muda de cara enquanto processa engana a pessoa a clicar de novo — e ela clica mesmo.

Um componente interativo nunca existe em um único estado visual. Ele muda de cara conforme a situação: parado, sob o mouse, focado pelo teclado, sendo clicado, desabilitado, carregando, com erro. Ignorar esses estados — codar só a aparência "parada" e nada mais — é a diferença entre um componente que parece confiável e um que parece quebrado, mesmo funcionando por baixo.

Os estados essenciais

  • :hover — sinaliza "isso é interativo" quando o mouse passa por cima, antes de qualquer clique.
  • :focus-visible — sinaliza qual elemento está ativo pra navegação via teclado.
  • :active — feedback imediato de que o clique foi registrado, no instante em que ele acontece.
  • disabled — sinaliza que a ação não está disponível agora (não que ela nunca vai estar).
  • loading — sinaliza que uma ação está em andamento e ainda não terminou.
  • erro — sinaliza que algo deu errado e, idealmente, o que fazer a respeito.
Estados de um botão em CSS
.botao {
  background: #2563eb;
  transition: background 150ms ease;
}
.botao:hover      { background: #1d4ed8; }
.botao:active     { background: #1e40af; transform: translateY(1px); }
.botao:disabled   { opacity: 0.5; cursor: not-allowed; }
.botao:focus-visible { outline: 2px solid #93c5fd; outline-offset: 2px; }

Por que o estado de loading não é opcional

Considere um botão "Salvar" que dispara uma requisição de rede e demora 800ms pra responder. Se o botão não muda de aparência nesse intervalo, a pessoa que clicou não tem nenhuma confirmação de que algo está acontecendo — o cérebro dela conclui "não funcionou" e ela clica de novo. Se a ação não for idempotente (por exemplo, criar um registro), isso pode disparar a mesma ação duas vezes.

Estado de loading evitando clique duplicado
.botao.is-loading {
  pointer-events: none; /* impede novo clique enquanto processa */
  opacity: 0.7;
}
.botao.is-loading::after {
  content: "";
  /* spinner ou indicador visual entra aqui */
}

O ponto central: o feedback visual não é sobre deixar a interface "mais viva" — é sobre a pessoa nunca ficar na dúvida entre "não funcionou" e "está processando". Essas duas situações exigem reações opostas (clicar de novo vs. esperar), e sem feedback visual claro é impossível saber qual delas é a verdadeira.

Exercício

Um formulário de cadastro envia os dados ao clicar em "Criar conta", mas o botão continua com a mesma aparência durante os 2 segundos que o servidor demora pra responder. Que classe de estado está faltando, e o que ela deveria fazer visualmente e funcionalmente?

Quiz rápido

Por que um botão sem nenhum feedback visual de 'carregando' durante uma ação assíncrona é um problema?
O que diferencia visualmente um botão no estado disabled de um botão comum?