GH GambleHub

Built-in validation and UX errors

1) Principles

1. Predictive care, not punishment. We show how to enter correctly, before the error.
2. Do not lose data. Any error does not destroy the entered; support Cancel/Retry.
3. Moment of display.

Before entering: helper text (rules and examples).
During: soft hints/mask/auto-substitution.

After (blur/submit): a clear error with the instruction "how to fix."

4. Attention economy. One message is one reason and one action.
5. Accessibility. Text + icon/color, link to the field via ARIA, focus to the first erroneous field.


2) Validation layers

Client synchronous: format, length, mandatory, mask. Fast and cheap.
Client asynchronous: login uniqueness, BIN/IBAN check, API hints. With debunking.
Server room: business rules, limits, risk scoring, authorization/rights. Truth of last resort.
Rule: even with an ideal client check, the server confirms and generates the final text.


3) Timings and debunks

Confirmation of success - laconic ("Ok") or green icon; without "salutes."

Validation for blur → instant feedback ≤ 100 ms.
Asynchronous check - debit 250-400 ms after input stop.
On 'submit' we show the list of errors and transfer focus to the first.

js const debounce = (fn, ms=300)=>{let t;return (...a)=>{clearTimeout(t);t=setTimeout(()=>fn(...a),ms)}}

4) Copywriting errors

Template: reason → how to fix → alternative (if any).

Good: "The password is shorter than 8 characters. Add more characters or use a phrase.

Good: "IBAN doesn't look right. Check length and characters: A-Z, 0-9."

Bad: "Incorrect input."

Don't blame the user; avoid jargon and codes.
In sensitive areas (payments/ASC), we avoid details that reveal safety.


5) Message display patterns

5. 1 At the field (inline)

`aria-invalid="true"`, текст в `aria-describedby`.
Briefly, specifically; without long paragraphs.
Color + icon, but meaning - in the text.

5. 2 Below the form (summary)

Lists all errors with field anchors.
The "Go to error" button/clicking on an item shifts focus.

5. 3 In the process of sending

Block repeated pressing (state 'busy').
With a timeout of 3-5 s - "Waiting for confirmation"... with a safe replay.


6) Masks, auto-tips and proofreaders

Masks should not interfere with insertion/editing. Allow free entry, normalize under the hood.
Auto-tips: show sample formats, placeholder as a hint, not a "required" part.
Normalization: trimming spaces, unifying registers, auto-format (for example, '+ 1 (___) ___ - ____') - but keep the "clean" version in the source data.


7) Availability (A11y)

Link: 'label' ↔ 'input', errors in 'aria-descripedby'.
Critical - 'role = "alert"', informational - 'role = "status"'.
We return focus to the erroneous field, ': focus-visible' we see.
Text/icon contrast ≥ AA; meaning does not depend only on color.

html
<label for="email">Email</label>
<input id="email" name="email" aria-describedby="email-help email-err">
<small id="email-help">Например: user@domain.tld</small>
<p id="email-err" class="field-error" role="alert" hidden>Проверьте формат email</p>

8) International formats and localization

Names/addresses: allow different alphabets, lengths, apostrophes, hyphens.
Dates/currencies/numbers: Use local input formats and strict internal storage structures (ISO/number of cents).
Phone: input in international format '+ CC', auto-hint by country.
Message language: short, culturally neutral; lay down + 20-30% of the line length.


9) Security and privacy

Do not show that the account exists/does not exist - the general text: "If the email is registered, we will send an email."

On critical steps (bid/pay) use idempotence and "safe replays."

Mask sensitive data (PAN, passport).
Logs - with correlation ID without PII in messages.


10) Saving progress

Draft autosave (local/server).
In case of submission error - the form remains filled in; suggested repeat later.
For Multi-Step Processes (KYC) - Save completed steps.


11) Asynchronous validation

Debowns 250-400 ms; we show "check..." near the field without blocking the entire screen.
Clear indication of success/failure without "twitching" of the layout.
Network timeout → "Unable to verify. Do you want to continue with the risk? (if applicable) or Redo.

js const checkUsername = debounce(async (v)=>{
state.usernameChecking = true;
const ok = await api.unique('username', v).catch(()=>null);
state.usernameChecking = false;
state.usernameValid = ok === true;
}, 300);

12) Payment forms and KYC (specifics)

Maps: PAN format, term, CVC - validation as entered; errors - without disclosing the reason for the rejection by the bank.
A2A/wallets: verification of admissibility by country/limits, clear texts about commissions/deadlines.
KYC: step-by-step requirements for photos/documents, preview, file size/type, verification time, privacy.
Responsible play: messages are neutral, with "Set limit "/" Help "actions.


13) Antipatterns

Show "per character" errors without debunking.
Resets the form on error.
"Invalid entry" message without field/rule.
Critical information only by color/icon.
Lock the entire page to validate a single field.
Absence of offline mode and repetitions during network failures.


14) Design system tokens (example)

json
{
"validation": {
"debounceMs": 300,
"blurFeedbackMs": 100,
"asyncTimeoutMs": 5000,
"summaryMaxItems": 6
},
"a11y": {
"useAriaDescribedby": true,
"errorRole": "alert",
"statusRole": "status"
},
"visual": {
"fieldGap": 8,
"iconSize": 16,
"borderRadius": 10
}
}

15) Implementation snippets

Field with inline validator (format + server check):
js const rules = {
email: v => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)          "Проверьте формат email"
};
async function validateEmail(v){
const fmt = rules.email(v);
if (fmt!== true) return fmt;
try {
const r = await fetch(`/api/email/check?v=${encodeURIComponent(v)}`);
const { allowed } = await r.json();
return allowed? true: "Этот email недоступен. Выберите другой.";
} catch {
return "Не удалось проверить. Повторите позже.";
}
}
Focus error summary:
ts function focusFirstError() {
const err = document.querySelector('[aria-invalid="true"]');
if (err) err.focus({ preventScroll:false });
}
Save draft locally:
js const saveDraft = debounce(form => localStorage.setItem('draft', JSON.stringify(Object.fromEntries(new FormData(form)))), 500);
form.addEventListener('input', ()=>saveDraft(form));

16) Metrics and Control

Time-to-Fix.
Error rate by field and by reason (format/limits/server).
Retry success rate.
Proportion of abandoned shapes and pitch depth.
Full of prompts: CTR "Details," frequency of hiding prompts.


17) QA checklist

A11y

  • Focus moves to the first invalid field; 'aria-describedby '/' aria-invalid' set.
  • Contrast ≥ AA; messages are independent of color only.

Behavior

  • Built-in validation with debunking; errors appear no earlier than blur (except for critical masks).
  • A summary is generated on the submit, the fields are not cleared.
  • Asynchronous checks do not lock the page; there is a timeout and a replay.

Text

  • Reason + how to fix; no codes/guilt.
  • Localization does not break the layout; examples are relevant.

Safety

  • No PII leaks in messages; do not disclose the existence of the account.
  • Idempotency for critical operations.

18) Documentation in the design system

Components: 'FieldError', 'FormSummary', 'HelperText', 'BusyButton'.
Rule maps for typical fields (email, phone, password, address, IBAN, date).
Guides for debunking, asynchronous checking and offline behavior.
Text templates for frequent errors and before/after examples.


Brief summary

Built-in validation is about predictive care, clear instructions and careful attitude to data. Check locally and on the server, show errors at the right time with specific actions, respect availability and privacy, save progress and use debuns. So forms become friendly, and mistakes become fast and fixable.

Contact

Get in Touch

Reach out with any questions or support needs.We are always ready to help!

Start Integration

Email is required. Telegram or WhatsApp — optional.

Your Name optional
Email optional
Subject optional
Message optional
Telegram optional
@
If you include Telegram — we will reply there as well, in addition to Email.
WhatsApp optional
Format: +country code and number (e.g., +380XXXXXXXXX).

By clicking this button, you agree to data processing.