Processamento de erros e explicação UX
1) Por que isso é importante
O erro não é um «texto vermelho», mas uma extensão do cenário. Bons erros UX:- explica o que aconteceu e o que fazer a seguir
- preserva os dados introduzidos e impede a perda de progresso,
- dá uma repetição segura ou um caminho alternativo,
- fica disponível (SR/teclado) e não revela nada demais.
2) Tipologia de erro (para interface)
1. Validação de dados (4xx cliente): campos em branco/errado, formato, comprimento, conflito de regras.
2. Regras de negócios: limites, limitações geo, KYC/KYB, duplos, slots inacessíveis.
3. Direitos/permissões: papel, acesso ao recurso, restrições de idade.
4. Rede/servidor: timeout, off, 5xx, sobrecarga, rate limit.
5. Conflito/estado: 409/412 (dados alterados), corrida, bloqueio.
6. Falta do recurso: 404/410, removido/transferido.
7. Pagamento e risco: desvio de banco/PSP, antifrode, limites de jogo responsável.
3) Canais e nível de exibição
Selecionando «volume» para o contexto:Regra: não esconda o crítico em brinde/hover. Onde o usuário vê, há uma mensagem.
4) Copiar erros
Estrutura, causa → consequência → ação.
Honesto, neutro, sem culpa.
Especifique um campo/condição, evite códigos e vidros.
O botão de ação é «Repetir», «Editar mapa», «Reativar filtros», «Abrir bate-papo».
Dados sensíveis: não mostrar (camuflagem PAN, atributos pessoais).
Exemplos
Certo: "O pagamento falhou, o banco rejeitou a transação. Tente outra forma ou repita mais tarde".
Mal, "Erro 500. Algo correu mal".
Certo: "O limite de despesas diárias será atingido. Estabeleça um novo limite ou tente amanhã".
Certo: "Arquivo é muito grande (máximo de 25 MB). Corte ou carregue vários arquivos".
5) Comportamento e foco (A11y)
O erro é exibido em um contexto focal: transforma o foco no primeiro campo errado.
As regiões vivas são 'role =' status '(polite) para informações,' role = 'alert' (assertive) para críticos.
Visível ': focus-visível', contraste de ≥ AA, alternativas de cor (ícone/texto).
A mensagem é ligada ao campo através de 'ária-describedy'.
html
<label for = "pwd "> Password </label>
<input id="pwd" name="password" aria-describedby="pwd-err" aria-invalid="true">
<p id = "pwd-err" role = "alert"> Minimum 8 characters </p>
6) Retraias, backoff e idempotação
A repetição é oferecida se houver chance de sucesso (falhas de rede, 5xx, rate limit).
Backoff exponencial 1-2-4-8 s, limite de tentativa, botão «Repetir» compreensível.
Transações críticas (apostas/pagamentos): Idempotency-Key obrigatório → excluindo duplicações.
Reversões de atualizações otimistas - retorno visual claro + explicação.
js async function retry(fn, attempts=3){
let wait=1000; for(let i=0; i<attempts; i++){
try{ return await fn(); }catch(e){ if(i===attempts-1) throw e; await new Promise(r=>setTimeout(r,wait)); wait=2; }
}
}
7) Off-line, timeouts e conteúdo parcial
Off-line: mostra o banner «Sem conexão», acesso a caju (read-only), fila de sincronização.
Timeout: Tempo UI (3-5 c) → estado «Aguardando confirmação»... com repetição/cancelamento seguro.
Sucesso parcial: preservamos o que conseguimos; marcamos «não sincronizado».
8) Conflitos e competitividade
409/412: Dados obsoletos. Sugerir «Atualizar» e mostrar o diff (o que mudou).
Bloqueios: Informando quem mantém o bloco e quanto tempo, botão Pedir acesso.
9) Modelos UI
Banner da página:html
<div class="banner banner--error" role="alert">
<strong> Connection failed. </strong> Shows cached data.
<button class =" btn btn--ghost" id = "retry "> Retry </button>
</div>
Modalk de erro crítico:
html
<div role="alertdialog" aria-labelledby="err-title" aria-describedby="err-desc">
<h2 id = "err-title "> Session expired </h2>
<p id = "err-desc "> Sign in again to continue. </p>
<button class = "btn "> Sign in </button>
<button class =" btn btn--ghost"> Home </button>
</div>
React ErrorBoundary (com ID de correlação):
tsx function Fallback({ id, onRetry }: { id: string; onRetry: ()=>void }) {
return (
<div role="alert" className="banner banner--error">
<strong> We couldn't load the page. </strong>
<div> Try again. Код: <code>{id}</code> <button onClick={()=>navigator. clipboard. writeText (id)}> Copy </button> </div>
<button onClick = {onRetry}> Retry </button>
</div>
);
}
10) Tocos de erro (sistema de design)
json
{
"error": {
"tones": { "danger": "#", "warning": "#", "info": "#" },
"aria": { "polite": true, "assertive": true },
"timing": { "toastMs": 3500, "retryBackoffMs": [1000,2000,4000] },
"layout": { "fieldGap": 8, "bannerIcon": 20 }
}
}
Os presídios CSS:
css
.banner--error { background: var(--bg-danger); color: var(--on-danger); padding: 12px 16px; border-radius: 12px; }
.field-error { color: var(--role-danger); margin-top: 6px; font-size:.875rem; }
11) Segurança e privacidade
Não tiramos pilhas, identificações internas, caminhos de BD.
Camuflamos os valores sensíveis (mapas, documentos).
As mensagens não devem dizer ao agressor (por exemplo, que existe uma conta).
Para suporte - ID de correlação em vez de peças.
json
{"level":"error","event":"payment_fail","correlation_id":"c-8f1...","user_id":"u-","route":"/pay","psp_code":"DO_NOT_EXPOSE_TO_USER"}
12) Métricas e controle
INP e participação de Long Tasks no momento do erro (erro não deve «pendurar» UI).
Retry sucess rate, erros em 1.000 ações, tempo até a recuperação.
CTR para Ajuda/Bate-papo, porcentagem de formulários abandonados.
Mapas térmicos: onde mais ocorre field-errors.
13) QA-folha de cheque
Disponibilidade
- Foco no primeiro campo errado; 'aria-describedy '/' aria-invalid' está exposto.
- Mensagens críticas - 'role =' alert '; contraste ≥ AA.
Comportamento
- Os dados do formulário não são perdidos por erro.
- Há um 'Retry' claro e um backoff correto.
- Modo off-line/kesh funcionam; Estamos a ver o banner.
Copiar
- Razão → ação; sem jargão técnico ou acusações.
- Os textos são localizados e não quebram a grade.
Segurança
- Sem fuga de PII/segredos; mostramos apenas códigos seguros/ID.
- Idempotidade ativada para operações críticas.
14) Especificidades iGaming
Aposta:- A UI capta imediatamente «busy»; com atraso> 3 c - «Aguardando confirmação»....
- Fail: status honesto («o mercado fechou», «o coeficiente mudou») + seguro «Retry».
- Chave Idumpotente para eliminar a aposta dupla.
- Distinguindo «falha do banco/PSP» vs «falha do servidor». Para o primeiro, «Escolha outro método», e para o segundo, «Retry».
- Passos transparentes KYC/AML; links "Por que é necessário? ».
- O tom é atencioso, sem pressão. O limite foi alcançado - faça uma pausa ou atualize o limite.
- Sem flashes/neon; contraste AAA, disponibilidade em SR.
- Explique claramente as limitações e sugira «Ler as regras/suporte».
15) Anti-pattern
Algo correu mal sem acções ou contexto.
Redefinir formulário após erro.
Esconder o crítico num brinde por 3 segundos.
Só cor sem texto/ícone.
Retraias infinitas sem possibilidade de cancelamento.
Mostrar códigos internos/pilhas.
16) Documentação em design
Компоненты: `FieldError`, `FormError`, `PageBanner`, `AlertDialog`, `ErrorBoundary`.
Tokens tons/contraste/temporizações, presetos a11y e exemplos de ARIA.
Mapa de cenários típicos (validação, rede, direitos, pagamentos) com modelos de texto.
«Do/Don 't»: telas reais antes/depois com métricas de falha/sucesso.
Resumo curto
Tornem os erros compreensíveis e controláveis: falem a língua humana, guardem os dados digitados, ofereçam uma repetição segura e alternativas, respeitem a acessibilidade e privacidade. Então, mesmo situações erráticas mantêm a confiança e não interrompem o caminho do usuário - especialmente em cenários críticos de apostas e pagamentos.