Artigos aprofundados sobre a tecnologia que molda o que vem a seguir.

Os Piores Anti-Padrões de UX e Como Corrigi-los

Os piores anti-padrões de UX ainda em produção, com correções antes e depois para dark patterns, toggles quebrados e acessibilidade.

Parede de toggles todos ligados, um botão azul brilhante e enorme ao lado de um pequeno interruptor cinza escondido.

Semana passada tentei ajustar as preferências de cookies no site de uma grande companhia aérea. O botão 'Aceitar tudo' era um azul vibrante, impossível de não ver. O link 'Gerenciar preferências'? Texto cinza, fonte de 11px, escondido embaixo de um parágrafo de juridiquês. Quando finalmente achei, caí numa página com 47 toggles individuais, todos ligados por padrão, e nenhum botão 'Rejeitar tudo' à vista. Fiquei um minuto inteiro clicando em toggles até desistir e simplesmente apagar os cookies manualmente.

Isso não é um caso isolado. É a regra. UX ruim não é só irritante, é hostil. E o pior? A maioria desses anti-padrões tem correções simples que levam menos tempo para implementar do que a ginástica de dark patterns que eles substituem. Eu construo aplicações web há mais de dez anos e fico genuinamente perplexo por continuarmos lançando essas coisas. Então vamos falar dos piores culpados e como eliminá-los.

Dark Patterns que Tratam Usuários como Alvos

Dark patterns não são acidentes. Alguém sentou numa reunião, olhou para as métricas de conversão e decidiu que enganar usuários era uma estratégia de negócio aceitável. É isso que os torna tão irritantes: eles são deliberados.

Confirmshaming: Culpa como Elemento de Interface

Você já viu esses. Um modal aparece pedindo para assinar uma newsletter. O botão de aceitar diz 'Sim, quero economizar!'. O botão de recusar diz 'Não, obrigado, prefiro pagar preço cheio'. Isso é confirmshaming, e está em todo lugar: sites de e-commerce, fluxos de onboarding de SaaS, até algumas ferramentas para desenvolvedores. Funciona com uma pequena porcentagem de usuários e afasta todo o resto.

A correção é constrangedoramente simples: use linguagem neutra para as duas opções.

<!-- BEFORE: Manipulative confirmshaming -->
<div class="modal">
<p>Join 50,000 smart developers!</p>
<button class="btn-primary">Yes, sign me up!</button>
<button class="btn-link text-sm">
No thanks, I don't care about my career
</button>
</div>
<!-- AFTER: Respectful, neutral options -->
<div class="modal">
<p>Get weekly frontend tips — no spam, unsubscribe anytime.</p>
<button class="btn-primary">Subscribe</button>
<button class="btn-secondary">No thanks</button>
</div>

Repare que a versão depois também deixa de lado a prova social inflada e adiciona uma promessa clara sobre spam. Respeito gera mais confiança do que manipulação. Sua conversão de longo prazo vai agradecer.

O Roach Motel: Cadastro em Um Clique, Cancelamento em Sete Passos

Fazer cadastro leva 30 segundos. Cancelar exige navegar por Configurações > Conta > Assinatura > Gerenciar Plano > Cancelar Plano > Conte-nos o Motivo > Tem Certeza > Fale com a Retenção > Cancelar de Verdade. Alguns serviços ainda exigem uma ligação telefônica. Em 2026. Para cancelar uma assinatura que você começou com um único clique.

Não me importo com o que suas métricas de retenção dizem. Usuários presos não são clientes fiéis, são reféns gerando chargebacks e avaliações de uma estrela. Deixe o cancelamento exatamente tão fácil quanto o cadastro.

  • Coloque a opção de cancelar em Configurações da Conta, onde as pessoas esperam encontrá-la
  • No máximo dois passos: 'Tem certeza?' e depois 'Pronto, sua conta foi cancelada'
  • Não esconda o botão de cancelar atrás de um link de 'Falar com o Suporte'
  • Se você oferecer um desconto de retenção, tudo bem, mas não o torne um passo obrigatório no fluxo
  • Envie um e-mail de confirmação com um link de reativação, em vez de fazer o cancelamento parecer irreversível

Toggles Quebrados e Controles de Interface Confusos

Aqui vai um experimento divertido: vá às configurações do seu celular e conte quantos toggles você não consegue identificar de imediato se estão ligados ou desligados. Eu espero.

O toggle ambíguo é uma das falhas de UI mais comuns que encontro em code reviews. Um toggle deve comunicar exatamente uma coisa: o estado atual. Isso está ligado ou desligado? Só isso. Mas desenvolvedores continuam lançando toggles em que os dois estados parecem quase idênticos, ou em que o código de cores é ambíguo, ou em que o toggle mostra o que vai acontecer em seguida em vez do que está acontecendo agora.

/* BEFORE: Both states look nearly identical */
.toggle {
width: 48px;
height: 24px;
background: #d1d5db;
border-radius: 12px;
cursor: pointer;
}
.toggle.active {
background: #9ca3af; /* barely different from inactive */
}
/* AFTER: Unmistakable state difference + accessible */
.toggle {
width: 48px;
height: 24px;
background: #d1d5db;
border-radius: 12px;
cursor: pointer;
position: relative;
}
.toggle[aria-checked="true"] {
background: #2563eb; /* strong contrast from inactive */
}
.toggle .label {
font-size: 10px;
font-weight: 600;
color: white;
}
.toggle[aria-checked="true"] .label::after { content: "ON"; }
.toggle[aria-checked="false"] .label::after { content: "OFF"; }

Três regras para toggles que não confundem as pessoas: cores distintas para cada estado (com contraste suficiente para funcionar com usuários daltônicos), um rótulo de texto dentro ou ao lado do toggle, e atributos aria-checked adequados para que leitores de tela anunciem o estado. Se você depende apenas da cor, falhou em UX e em acessibilidade de uma só vez.

Pare de Reinventar Controles de Formulário Nativos

Reviso muitos PRs de frontend, e um padrão me tira do sério: dropdowns feitos na mão que quebram a navegação por teclado. Um desenvolvedor passa dois dias construindo um menu select sofisticado do zero, com um monte de divs e handlers de clique. Fica ótimo na demo. Aí um usuário tenta navegar com Tab por um formulário, chega no dropdown customizado e nada acontece. Sem suporte a setas. Sem busca por digitação. Não funciona com gerenciadores de senha. Quebra no mobile.

Enquanto isso, o elemento nativo <select>, ou uma biblioteca bem testada como Radix UI ou Headless UI, resolve tudo isso de graça. A API de popover do HTML e o elemento <selectlist> já têm suporte sólido nos navegadores. Use. Seus usuários não se importam se o seu dropdown tem uma animação customizada. Eles se importam que funcione.

Anti-Padrões de Acessibilidade que Excluem Usuários Reais

Acessibilidade não é um diferencial desejável. Não é uma funcionalidade que você adiciona numa sprint futura. Mais de um bilhão de pessoas no mundo convivem com alguma forma de deficiência, e o relatório WebAIM Million aponta consistentemente que 96%+ dos um milhão de sites mais acessados apresentam falhas de WCAG detectáveis. Não são casos obscuros: são botões quebrados, rótulos ausentes e imagens sem texto alternativo.

Aqui está o que eu vejo com mais frequência:

  1. Imagens sem texto alternativo: leitores de tela só dizem 'imagem' e seguem em frente
  2. Razões de contraste abaixo de 4,5:1: o texto fica ilegível para usuários com baixa visão
  3. Sem navegação por teclado: se você não consegue navegar com Tab pela sua aplicação, usuários de teclado e de dispositivos de comutação ficam de fora
  4. Armadilhas de foco em modais: o usuário abre um diálogo e não consegue sair dele sem o mouse
  5. Campos de formulário sem rótulo: o leitor de tela não faz ideia do que é aquele campo
  6. Vídeo com reprodução automática e sem botão de pausa: desorientador para usuários com transtornos vestibulares

A vitória mais rápida é adicionar verificações automatizadas de acessibilidade ao seu pipeline de CI. Elas não pegam tudo (ferramentas automáticas encontram talvez 30 a 40% dos problemas), mas pegam o óbvio antes que chegue à produção.

// BEFORE: No accessibility testing at all
test('homepage loads', async ({ page }) => {
await page.goto('/');
await expect(page.locator('h1')).toBeVisible();
});
// AFTER: Accessibility violations fail the build
import AxeBuilder from '@axe-core/playwright';
test('homepage loads and is accessible', async ({ page }) => {
await page.goto('/');
await expect(page.locator('h1')).toBeVisible();
const a11yResults = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa'])
.analyze();
expect(a11yResults.violations).toEqual([]);
});

Cinco minutos de configuração. Roda em todo PR. Detecta texto alternativo ausente, roles de ARIA quebrados, contraste insuficiente e dezenas de outras falhas automaticamente. Não há desculpa para não fazer isso.

Sobrecarga Cognitiva: A Página de Configurações do Inferno

A memória de trabalho humana guarda cerca de quatro a sete itens por vez. Isso não é uma sugestão, é um limite cognitivo rígido. Quando sua interface despeja 200 opções numa única página sem hierarquia, você não está dando controle ao usuário. Está dando paralisia de decisão.

Certa vez contei as configurações de uma ferramenta de gestão de projetos que usávamos no trabalho. 347 opções. Uma página. Sem busca. Sem agrupamento além de categorias vagas como 'Geral' e 'Avançado'. Metade do time nunca tinha alterado uma única configuração, porque a página era tão avassaladora que simplesmente fechavam na hora.

A correção é a divulgação progressiva. Mostre as cinco configurações que as pessoas realmente mudam. Coloque todo o resto atrás de seções expansíveis claramente rotuladas. Adicione uma barra de busca. E, pelo amor de tudo, forneça padrões sensatos para que a maioria dos usuários nunca precise da página de configurações.

Se a sua página de configurações precisa de documentação própria, a página de configurações é o problema.

A Sobrecarga de Notificações Ensina os Usuários a Ignorar Tudo

Quando cada evento dispara uma notificação (um colega entrou num canal, alguém reagiu com um emoji, um deploy terminou, um evento do calendário começa em 30 minutos), os usuários aprendem a ignorar todas elas. Você transformou seu sistema de notificações em ruído branco. O único alerta crítico que realmente importa? Enterrado debaixo de 47 notificações não lidas.

Padrões conservadores são a resposta. Novos usuários devem receber apenas notificações críticas. Agrupe o que não é urgente num resumo diário. E sempre, sempre, permita que o usuário silencie ou personalize diretamente a própria notificação, e não numa página de preferências escondida a três cliques de distância.

UI Lenta é UI Quebrada: Performance como Problema de UX

Um botão que leva dois segundos para responder não está lento. Está quebrado. O usuário não pensa 'ah, o servidor está processando minha requisição'. Ele pensa 'será que meu clique foi registrado?' e clica de novo. Agora você tem envios duplicados, estado confuso e um usuário que não confia no seu app.

Qualquer coisa acima de 100ms parece travada. Qualquer coisa acima de um segundo quebra a linha de raciocínio do usuário. Mesmo assim, continuamos lançando bundles de JavaScript de vários megabytes, scripts de terceiros bloqueando a renderização e deslocamentos de layout que fazem as pessoas clicarem no elemento errado. A correção não é complicada, só exige se importar com isso.

// BEFORE: User clicks, waits 2 seconds, nothing happens
async function handleLike(postId: string) {
const result = await fetch(`/api/posts/${postId}/like`, {
method: 'POST',
});
if (result.ok) {
setLikeCount(prev => prev + 1); // UI updates after network round-trip
}
}
// AFTER: Optimistic update — UI responds instantly
function handleLike(postId: string) {
// Update UI immediately
setLikeCount(prev => prev + 1);
// Sync with server in background
startTransition(async () => {
const result = await fetch(`/api/posts/${postId}/like`, {
method: 'POST',
});
if (!result.ok) {
// Rollback only on failure
setLikeCount(prev => prev - 1);
toast.error('Something went wrong. Try again.');
}
});
}

Atualizações otimistas, telas de esqueleto no lugar de spinners, JavaScript não crítico com carregamento lazy e monitoramento dos Core Web Vitals como métricas reais, não como reflexão tardia. Essas não são técnicas avançadas. São expectativas básicas.

Anti-Padrões de UX Mobile que Se Recusam a Morrer

O mobile tem sua própria categoria especial de pecados de UX, principalmente porque desenvolvedores continuam testando num iPhone novinho e dando o assunto por encerrado.

Áreas de Toque que Exigem Precisão Cirúrgica

As diretrizes da Apple dizem 44x44 pixels CSS como mínimo para áreas de toque. O WCAG 2.2 concorda. Mesmo assim, ainda vejo botões de fechar de 20 pixels em modais, links minúsculos amontoados em rodapés e botões de ícone quase impossíveis de acertar num celular. É ainda pior para usuários com deficiências motoras.

/* BEFORE: Tiny, frustrating touch targets */
.close-btn {
width: 20px;
height: 20px;
font-size: 12px;
}
.footer-links a {
padding: 2px 4px;
font-size: 11px;
}
/* AFTER: Actually tappable elements */
.close-btn {
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
}
.footer-links a {
padding: 12px 8px;
font-size: 14px;
/* spacing between adjacent targets */
margin: 4px 0;
}

Intersticiais em Tela Cheia que Bloqueiam o Conteúdo

Você toca num resultado de busca. A página carrega. Antes que consiga ler uma única palavra, um modal em tela cheia exige seu e-mail. Você nem viu o conteúdo ainda. Por que você assinaria?

O Google penaliza intersticiais intrusivos nos rankings de busca desde 2017. Eles continuam existindo porque alguém, em algum lugar, olha para um painel que mostra uma taxa de captura de e-mails de 2% e comemora, ignorando a taxa de rejeição de 40% que isso causa. Use banners inline ou bottom sheets. Espere até que o usuário tenha realmente interagido com o conteúdo antes de pedir qualquer coisa. Um leitor que terminou três artigos vai assinar com vontade. Um leitor que foi interrompido três vezes vai sair e nunca mais voltar.

Como Construir uma Cultura de Qualidade em UX (Não Apenas Corrigir Bugs Isolados)

Corrigir anti-padrões um por um é necessário, mas não suficiente. Se o seu processo continua produzindo-os, você precisa de um processo melhor. Aqui está o que realmente funciona:

  1. Adicione o axe-core ao seu pipeline de CI: verificações automatizadas de a11y em todo PR
  2. Faça da revisão de UX parte do code review, e não um processo separado só de design
  3. Teste com 5 usuários reais antes de lançar funcionalidades importantes: 5 usuários revelam cerca de 85% dos problemas de usabilidade
  4. Acompanhe taxas de conclusão de tarefas e taxas de erro, não apenas visualizações de página e tempo no site
  5. Use um design system com componentes acessíveis prontos, para que os devs individuais não precisem resolver os mesmos problemas de interação do zero
  6. Use o seu próprio produto de forma implacável: quando o desenvolvedor que construiu a página de configurações precisa usá-la todo dia, ela é corrigida rapidamente

A melhor melhoria de UX que já fiz começou comigo tentando usar nosso próprio fluxo de checkout no celular e xingando no canal do produto às 23h.

Cada anti-padrão deste artigo tem uma correção direta. Nenhum deles exige tecnologia de ponta ou redesenhos gigantescos. Eles exigem se importar de verdade. Comece com uma correção hoje. Faça uma auditoria de acessibilidade nesta semana. Teste com um usuário real neste mês. Um bom UX não é feito de grandes gestos, é feito de escolher consistentemente o respeito pelos usuários em vez de métricas de curto prazo. A distância entre o software que as pessoas toleram e o que elas amam é menor do que você imagina. São apenas mil pequenas decisões, bem tomadas.