Masques de saisie et formulaires UX
1) Principes
1. Aider, ne pas punir. Le masque guide la saisie et réduit les erreurs, mais ne bloque pas l'impression et l'insertion.
2. Données ≠ affichage. Nous stockons les valeurs normalisées « brutes », nous ne formatons que dans l'interface utilisateur.
3. Curseur prévisible. Toute sélection automatique ne « saute » pas caret et ne casse pas undo/redo.
4. Local et appareil. Claviers, séparateurs, calendrier et devises - par région et plate-forme.
5. Accessibilité et intimité. Texte + icône/couleur ; les champs sensibles sont masqués, mais ne gênent pas les gestionnaires de mots de passe/remplissage automatique.
2) Quand le masque est approprié (et quand pas)
Utiliser :- Formats avec structure stable : téléphone, IBAN, PAN (cartes), CVC, date, heure, index, OTP.
- Sommes d'argent séparées (entrée « pure » lors de l'impression, format de blues).
- Codes (réf. codes, promos), longueurs fixes.
- Noms/Adresses/Email (le masque limite les caractères/langues valides).
- Champs libres complexes (commentaires, noms d'entreprise).
- Entrée avec un format potentiellement inconnu (numéros internationaux sans pays).
3) Masque vs auto format vs validation
Masque - conseil de structure à la volée (parenthèses, tirets) ; ne doit pas casser l'entrée/l'insertion.
Format automatique - appliqué en cas de blue/perte de focus (milliers, espaces IBAN).
La validation est la logique de l'exactitude (longueur, somme de contrôle), l'affichage des erreurs après 'blur' ou 'submit'.
Règle : le masque ne remplace pas la validation et l'auto-format ne doit pas changer le sens de ce que vous entrez.
4) Claviers et attributs HTML
Sélectionnez les types/modes corrects pour accélérer l'entrée et réduire les erreurs :5) Chariot, copipast et normalisation
Ne pas casser le caret : lors de l'insertion automatique de caractères (espaces/parenthèses), ajustez la position du curseur.
Copipast : lorsque vous vous collez, nettoyez les espaces/tirets → validez → affichez avec le formatage.
Normalisation : trimming, remplacement des « courbes » de caractères ('O'→'0' ne peut pas !), mise en majuscule pour IBAN, format de date unique dans le magasin (ISO).
js const clean = s => s. replace(/[^\da-zA-Z]/g,'');
const normalizePAN = s => clean(s). slice (0.19) ;//no spaces/hyphens const normalizeIBAN = s => clean (s). toUpperCase(); // A–Z0–9
6) Nombres, devises et locales
Entrée « comment imprimé » (tolérance ',' ou '.), stockage en unités mineures (centimes/cents).
Affichage localisé (groupement de milliers) sur le blur/après le sabmite ; dans le focus, montrez la valeur « brute » pour faciliter l'édition.
Indiquez clairement la devise et enregistrez la précision (par exemple, 2 caractères).
js function parseMoney(input) {
//resolve both comma and period as decimal const s = input. replace(/\s/g,''). replace(',', '.');
const num = Number(s);
if (Number. isNaN(num)) return null;
return Math. round(num 100); // cents
}
function formatMoney(cents, locale='ru-RU', currency='RUB') {
return (cents/100). toLocaleString(locale, { style:'currency', currency });
}
7) Dates et heures
Si les pickers natifs sont inconfortables/différents sur les plates-formes - utilisez la zone de texte avec le masque 'DD. MM. YYYY ', mais gardez ISO' YYYY-MM-DD'.
Vérification de la réalité des dates (29. 02, plages), les temporisations - sur le serveur.
Ajoutez les boutons « Aujourd'hui », « Maintenant », « Nettoyer ».
8) Téléphones et pays
Deux champs : pays (+ code) et numéro ou masque « intelligent » par pays sélectionné.
Si vous insérez un '+ CC...' complet, remplissez automatiquement le pays.
Gardez le E.164 ('+ CCXXXXXXXXXXXXXXXXXX'), affichez-le localement avec des espaces.
9) Détails de paiement : PAN/IBAN/CVC/BOU
PAN : regroupement des 4-4-4-4/4 ; au sens, seulement les chiffres ; Luhn-check; pas de logs/analystes avec PAN.
CVC : 'password' -style (caché), 'autocoplete =' cc-csc', ne pas enregistrer dans les brouillons.
BOU : 'MM/YY', auto-insertion '/' après 2 chiffres, vérification de la plage 01-12 et de l'année raisonnable.
IBAN : cas upper, lacunes uniquement dans l'IU ; vérification de la longueur par pays et de la somme de contrôle.
10) OTR/code de confirmation
6 (ou N) cellules autofocus et auto-transition, l'insertion du tampon reconnaît tout le code.
« autocoplete = » one-time-code « », sur les mobiles, une attraction automatique à partir d'un SMS.
Entrée backap sans champs de division (un champ) - pour les lecteurs d'écran.
html
<div class="otp" role="group" aria-label="Код из SMS">
<input inputmode="numeric" maxlength="1">
<input inputmode="numeric" maxlength="1">
<!-- … -->
</div>
11) Masques et a11y
Le label est obligatoire ('<label for>'), placeholder est un exemple, pas un remplacement.
Expliquez la règle à côté de : helper text avec un exemple (« Format : + CC XXX-XX-XX »).
Liez les erreurs via 'aria-describedby', les erreurs critiques sont 'role =' alert '.
Le contraste du texte et des contours ≥ AA, ': focus-visible' ne se cache pas.
12) Vie privée et sécurité
Champs sensibles : ne pas loger, ne pas écrire dans RUM, ne pas enregistrer dans les brouillons (PAN, CVC, passeport).
Les masques et le formatage ne doivent pas révéler la validité du compte (« Si l'email est enregistré... » - formulation neutre).
Idempotence et retry pour les sabmites critiques (paiement/taux).
13) Comportement des formes et performance
Debounce des contrôles asynchrones (250-400 ms), indication visible « On vérifie »....
Ne bloquez pas tout l'écran pour un seul champ ; spinner/squelette local.
Batchite les changements de DOM ; n'animez que « bou/opacity ».
Sur les mobiles - éviter les « sauts » lorsque le clavier apparaît (safe-area, viewport meta).
14) Code de retrait
Masque de téléphone souple (pas de tranches d'insertion) :js function formatPhoneVisible(value) {
const d = value. replace(/\D/g,''). slice(0,15);
if (!d) return '';
if (d. startsWith('7') d. startsWith('8')) {
return d. replace(/^([78])? (\d{3})(\d{3})(\d{2})(\d{2})./, '+7 ($2) $3-$4-$5');
}
// generic E.164 grouping: +CC XXX XXX XX XX return d. replace(/^(\d{1,3})(\d{0,3})(\d{0,3})(\d{0,2})(\d{0,2})./, (m,c1,c2,c3,c4,c5)=>
`+${c1}${c2?` ${c2}`:''}${c3?` ${c3}`:''}${c4?` ${c4}`:''}${c5?` ${c5}`:''}`.trim());
}
const input = document. querySelector('#phone');
input. addEventListener('input', e => {
const raw = e. target. value;
const pos = e. target. selectionStart;
const digitsBefore = raw. slice(0,pos). replace(/\D/g,''). length;
const cleaned = raw. replace(/[^\d+]/g,'');
const visible = formatPhoneVisible(cleaned);
e. target. value = visible;
// restore caret by counting digits let p = 0, count = 0;
while (p < e. target. value. length && count < digitsBefore) { if (/\d/.test(e. target. value[p])) count++; p++; }
e. target. setSelectionRange(p, p);
});
Somme : « brut au focus → format au blues » :
js const amount = document. getElementById('amount');
let cents = null;
amount. addEventListener('focus', () => {
if (cents!=null) amount. value = String(cents/100). replace('.', ',');
});
amount. addEventListener('blur', () => {
const v = parseMoney(amount. value) ;//from section 6 if (v = = null) return; cents = v;
amount. value = formatMoney(cents, 'ru-RU', 'RUB');
});
IBAN : cas upper et groupement dans le blues :
js const iban = document. getElementById('iban');
iban. addEventListener('input', () => iban. value = iban. value. toUpperCase());
iban. addEventListener('blur', () => {
const raw = normalizeIBAN(iban. value);
iban. dataset. raw = raw ;//for iban submission. value = raw. replace(/(.{4})/g,'$1 '). trim () ;//view only
});
15) Tokens de système de conception (exemple)
json
{
"input": {
"radius": 10,
"height": { "sm": 36, "md": 40, "lg": 48 },
"gap": 8,
"icon": 16
},
"mask": {
"debounceMs": 300,
"otpLength": 6,
"moneyPrecision": 2,
"phoneMaxDigits": 15
},
"a11y": {
"focusRing": { "width": 2, "offset": 2 },
"contrastAA": true
}
}
Presets CSS :
css
.input { height:40px; padding:0 12px; border-radius:10px; }
.input:focus-visible { outline:2px solid var(--focus-ring); outline-offset:2px; }
.field-error { color: var(--role-danger); font-size:.875rem; margin-top:6px; }
.otp input { width:40px; text-align:center; }
16) Spécificité iGaming
Paiements/conclusions : PAN/IBAN/amount avec masques souples ; la stricte idempotence et l'absence de loges de champs sensibles ; indices sur les commissions et les délais.
KYC : masques pour les dates, numéros de passeport (sans filtrage « rigide » - prise en compte de différents formats), taille/type de fichier, préprogramme.
Limites et jeu responsable : montants/périodes compréhensibles (jours/semaines/mois), helpers à proximité, contraste AAA.
Paris : entrée rapide de la somme (boutons presets + champ), en focus nombre « brut », en blues format local ; non-admission « , « ...../double séparateur.
17) Anti-modèles
Masques durs qui interdisent les caractères/inserts valides.
Caret sautant au format automatique ; perte d'allocation/undo.
Placeholder à la place du label.
L'ajout automatique de la monnaie à l'intérieur de la valeur (casse le copipast).
Erreurs « par caractère » sans débonse.
Formats locaux dépendants dans le référentiel (stockez ISO/nombres).
L'enregistrement des numéros PAN/passeports et l'affichage des raisons « trop honnêtes » de rejet.
18) Métriques et expériences
Taux d'erreur par champ (avant/après le masque).
Les formulaires Time-to-Complete et les retransmissions.
Proportion d'inserts échoués (copipast) et de « reculs » (undo).
CTR conseils/exemples, proportion de remplissage automatique.
Taux d'abandon à l'étape de paiement/CUS.
19) Liste de vérification QA
Entrée et caret
- L'insertion du tampon ne se brise pas, les espaces/tirets sont correctement nettoyés.
- Caret reste prévisible après le format automatique.
Local et format
- Les montants permettent ', '/'. stockage en unités mineures.
- Les dates partent et sont validées ; stockage dans l'ISO.
A11y
- Les labels et 'aria-describedby' sont connectés ; 'role =' alert 'pour les critiques.
- Le contraste et les anneaux de focus correspondent à AA.
Sécurité
- Les champs sensibles ne sont pas logés/mis en cache.
- Idempotence et retry sur les étapes critiques.
UX
- Placeholder est un exemple, pas un label ; helper est à côté.
- Les masques n'empêchent pas l'impression sur les mobiles ; claviers corrects ('inputmode').
20) Documentation dans le système de conception
Компоненты: `MaskedInput`, `MoneyInput`, `PhoneInput`, `OtpInput`, `IbanInput`.
Jetons de masque (longueurs/motifs), règles de caret/insertion, localisation des nombres/dates.
Hydes par la vie privée (ce qui ne peut pas être logé), par l'accessibilité et par le format automatique vs blues.
« Do/Don't » avec des exemples réels et des métriques avant/après.
Résumé succinct
Les masques et les formes sont bons quand ils accélèrent l'entrée, gardent les données propres et ne gênent pas. Formater avec soin, normaliser à l'entrée, stocker dans des vues stables, tenir compte des localités et de la disponibilité. Ensuite, les formulaires deviennent rapides et compréhensibles - en particulier dans les scénarios de paiement sensibles, KYC et les taux.