Gestione degli errori e spiegazioni UX
1) Perché è importante
L'errore non è testo rosso, ma lo script continua. Buon UX errori:- spiega cosa è successo e cosa fare dopo
- conserva i dati immessi e impedisce la perdita di progressi
- fornisce una ripetizione sicura o un percorso alternativo,
- rimane disponibile (SR/tastiera) e non mostra troppo.
2) Tipologia di errore (per interfaccia)
1. Convalida dati (4xx client) - Campi vuoti/non validi, formato, lunghezza, conflitto di regole.
2. Regole aziendali: limiti, limiti geo, KYC/KYB, prese, slot inaccessibili.
3. Diritti/permessi: ruolo, accesso alla risorsa, limiti di età.
4. Rete/server: timeout, offline, 5xx, sovraccarico, rate limit.
5. Conflitto/stato: 409/412 (dati cambiati), corse, blocchi.
6. Nessuna risorsa: 404/410, rimosso/spostato.
7. Pagamenti e rischi: deviazione della banca/PSP, antifrode, limiti di gioco responsabile.
3) Canali e livello di visualizzazione
Selezionando il volume nel contesto:Regola: non nascondere critico in toast/hover. Dove l'utente guarda, c'è un messaggio.
4) Copiratting degli errori
La causa della azione è l'effetto.
Il tono è onesto, neutrale, senza colpa.
Specifica: specificare un campo/condizione, evitare codici e vetri.
Pulsante-azione: Ripeti, Modifica mappa, Reimposta filtri, Apri chat.
Dati sensibili: non visualizzare (maschera PAN, attributi personali).
Esempi
Ok, "Il pagamento è fallito, la banca ha rifiutato la transazione. Provare un altro metodo o ripetere più tardi".
Male, "Errore 500. Qualcosa è andato storto".
Ok, "Il limite della spesa giornaliera è stato raggiunto. Impostare un nuovo limite o provare domani".
Ok, "File troppo grande (massimo 25 MB). Cucire o scaricare più file".
5) Comportamento e attivazione (A11y)
L'errore viene visualizzato in un contesto focale in cui viene attivato il primo campo non valido.
Regioni viventi: 'role = status' (polite) per info, 'rolle =' (assistenziale) per critici.
Visibile'focus-visual ', contrasto del colore AA, alternativa al colore (icone/testo).
Il messaggio viene collegato al campo tramite «aria-describedby».
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) Retrai, backoff e idampotenza
La ripetizione viene offerta se c'è una possibilità di successo (guasti di rete, 5xx, rate limit).
Backoff esponenziale 1-2-4-8 c, limite di tentativi, pulsante ripetizione comprensibile.
Transazioni critiche (scommesse/pagamenti): Idempotency-Key obbligatorio escludiamo le riprese.
Ripristini aggiornamenti ottimistici - Restituzione visiva chiara e spiegazione.
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) Offline, timeout e contenuti parziali
Offline - Mostra il banner «Nessuna connessione», l'accesso alla cache (read-only), la coda di sincronizzazione.
Timeout: timeout UI (3-5 s) → stato «In attesa di conferma»... con ripetizione/annullamento sicuro.
Successo parziale: manteniamo ciò che è riuscito; contrassegniamo «non sincronizzato».
8) Conflitti e competitività
409/412: i dati sono obsoleti. Suggerisci di aggiornare e mostrare il diff (che è cambiato).
Blocchi: informiamo chi tiene il blocco e quanto tempo il pulsante Richiedi accesso.
9) Modelli UI
Banner pagina: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>
Modalina errore critico:
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 (con ID di correlazione):
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) Token di errore (sistema di progettazione)
json
{
"error": {
"tones": { "danger": "#", "warning": "#", "info": "#" },
"aria": { "polite": true, "assertive": true },
"timing": { "toastMs": 3500, "retryBackoffMs": [1000,2000,4000] },
"layout": { "fieldGap": 8, "bannerIcon": 20 }
}
}
Preset 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) Sicurezza e privacy
Non estraiamo stack roulotte, ID interni, percorsi di database.
Maschera i valori sensibili (mappe, documenti).
I messaggi non devono essere indicati all'aggressore (ad esempio, un account esistente).
Per il supporto, l'ID di correlazione al posto delle parti.
json
{"level":"error","event":"payment_fail","correlation_id":"c-8f1...","user_id":"u-","route":"/pay","psp_code":"DO_NOT_EXPOSE_TO_USER"}
12) Metriche e controllo
INP e la quota Long Tasks al momento dell'errore (l'errore non deve «appendere» UI).
Retry success rate, errori per 1000 azioni, tempo prima del ripristino.
CTR per Aiuto/Chat, percentuale di moduli abbandonati.
Mappe termiche: dove più spesso si verificano field-errors.
13) Lista assegni QA
Disponibilità
- Focus sul primo campo sbagliato; 'aria-describedby'/' aria-invalid'.
- Messaggi critici: 'rolle = «alert»; il contrasto dell'AA.
Comportamento
- I dati del modulo non vengono persi in caso di errore.
- C'è un'Retry "comprensibile e un backoff corretto.
- Modalità offline/cash funzionano; Lo striscione lo vediamo.
Copiating
- Causa dell'azione senza gergo tecnico e senza accuse.
- I testi vengono localizzati e non rompono la griglia.
Protezione
- Nessuna fuga di PII/segreti; mostra solo codici/ID sicuri.
- Idempotenza attivata per le operazioni critiche.
14) Specificità del iGaming
Puntata:- UI registra subito «busy»; in caso di ritardo> 3 c - «In attesa di conferma»....
- Fail: stato onesto («mercato chiuso», «fattore cambiato») + sicuro «Retry».
- Chiave idipotente per escludere la doppia puntata.
- Distinguiamo tra «guasto della banca/PSP» vs «guasto del server». Il primo è «Scegli un altro metodo», il secondo è «Retry».
- Passaggi trasparenti KYC/AML; I collegamenti "Perché è necessario? ».
- Il tono è premuroso, senza pressione. Il limite è stato raggiunto. Interrompere o aggiornare il limite.
- Senza flash/neon; contrasto AAA, disponibilità SR.
- Spieghi chiaramente le restrizioni e suggerisci «Leggi le regole/supporto».
15) Anti-pattern
«Qualcosa è andato storto» senza azioni e contesto.
Reimposta il modulo dopo un errore.
Nascondi il critico in un brindisi di 3 secondi.
Solo un colore senza testo o icona.
Retrai infiniti senza possibilità di cancellazione.
Mostra i codici interni/stack.
16) Documentazione in progettazione
Компоненты: `FieldError`, `FormError`, `PageBanner`, `AlertDialog`, `ErrorBoundary`.
Token tonalità/contrasto/timing, preset a11y e esempi di ARIA.
Mappa degli script tipici (convalida, rete, diritti, pagamenti) con modelli di testo.
«Do/Don't»: schermate reali prima/dopo con metriche di errore/successo.
Breve riepilogo
Rendete gli errori comprensibili e gestibili: parlate la lingua umana, conservate i dati immessi, offrite una ripetizione sicura e alternative, rispettate la disponibilità e la privacy. A quel punto, anche le situazioni non normali mantengono la fiducia e non interrompono il percorso dell'utente, soprattutto negli scenari critici di scommesse e pagamenti.