Máscaras de entrada y formularios UX
1) Principios
1. Ayudar, no castigar. La máscara dirige la entrada y reduce los errores, pero no bloquea la impresión y la inserción.
2. Datos ≠ visualización. Almacenamos valores normalizados «crudos», formateamos sólo en IU.
3. Cursor predecible. Cualquier sustitución automática no «salta» caret y no rompe undo/redo.
4. Local y dispositivo. Teclados, separadores, calendario y monedas por región y plataforma.
5. Accesibilidad y privacidad. Texto + icono/color; los campos sensibles son enmascarados, pero no interfieren con los gestores de contraseñas/autocompletar.
2) Cuando la máscara es apropiada (y cuando no)
Utilizar:- Formatos con estructura sostenible: teléfono, IBAN, PAN (tarjetas), CVC, fecha, hora, índice, OTP.
- Sumas de dinero con divisores (cuando se imprime es una entrada «limpia», cuando el blur es un formato).
- Códigos (ref. códigos, promociones), longitudes fijas.
- Nombres/direcciones/Correo electrónico (la máscara limita los caracteres/idiomas válidos).
- Campos libres complejos (comentarios, nombres de empresas).
- Entrada con formato potencialmente desconocido (números internacionales sin país).
3) Máscara vs autoformato vs validación
Una máscara es una pista de una estructura «sobre la marcha» (paréntesis, guiones); no debe romper la entrada/inserción.
Autoformato: se aplica en blues/pérdida de enfoque (miles, espacios IBAN).
La validación es la lógica de la corrección (longitud, sumas de comprobación), mostrando errores después de 'blur' o 'submit'.
Regla: la máscara no reemplaza la validación, y el autoformato no debe cambiar el significado de lo que se escribe.
4) Teclados y atributos HTML
Seleccione los tipos/modos correctos para acelerar la entrada y reducir los errores:5) Caret, copipast y normalización
No romper la careta: al insertar automáticamente los caracteres (espacios/paréntesis), ajuste la posición del cursor.
Copipast: al pegar, limpie los espacios/guiones → valide → muestre con formato.
Normalización: recortar, reemplazar «curvas» de caracteres (¡'O'→'0' no se puede!), mayúscula para IBAN, formato de fecha única en repositorio (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) Números, monedas y locales
Escribir "cómo se imprime" (tolerancia "," o ". como separador), almacenar en unidades menores (centavos/centavos).
Visualización por local (agrupación de miles) en blues/después de sabmita; en el enfoque, muestre el valor «crudo» para facilitar la edición.
Indique explícitamente la moneda y fije la precisión (por ejemplo, 2 signos).
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) Fechas y horas
Si los piqueros nativos son incómodos/diferentes en las plataformas - utilice el cuadro de texto con la máscara 'DD. MM. YYYY ', pero almacena el ISO' YYYY-MM-DD '.
Verificación de la realidad de las fechas (29. 02, rangos), zonas de tiempo - en el servidor.
Añada los botones «Hoy», «Ahora», «Limpiar».
8) Teléfonos y países
Dos campos: país (+ código) y número o máscara inteligente según el país seleccionado.
Al insertar un '+ CC...' completo, autocomplete el país.
Almacenar E.164 ('+ CCXXXXXXXXX'), mostrar localmente con espacios.
9) Detalles de pago: PAN/IBAN/CVC/AMB
PAN: agrupación 4-4-4-4/4; en valor - sólo dígitos; Luhn-check; sin registros/análisis con PAN.
CVC: 'password' -stil (oculto), 'autocomplete = "cc-csc'', no guardar en borrador.
AMB: 'MM/YY', auto-insertar '/' después de 2 dígitos, comprobar el rango 01-12 y un año razonable.
IBAN: upper-case, espacios sólo en UI; comprobación de la longitud del país y de la cantidad de comprobación.
10) OTR/código de confirmación
6 (o N) celdas con autofoco y auto-transición, insertar desde el búfer reconoce todo el código.
' autocomplete =» one-time-code»', en móviles - auto-atracción de SMS.
Entrada de respaldo sin campos divididos (un campo) - para los captores de pantalla.
html
<div class="otp" role="group" aria-label="Код из SMS">
<input inputmode="numeric" maxlength="1">
<input inputmode="numeric" maxlength="1">
<!-- … -->
</div>
11) Máscaras y a11y
El sello es obligatorio ('<label for>'), el placeholder es un ejemplo, no un reemplazo.
Explique la regla junto a: helper text con un ejemplo («Formato: + CC XXX XXX-XX-XX-XX»).
Los errores se vinculan a través de 'aria-describedby', los críticos son 'role =' alert '.
Contraste de texto y contornos ≥ AA, ': focus-visible' no ocultar.
12) Privacidad y seguridad
Campos sensibles: no lógica, no escribir en RUM, no guardar en borrador (PAN, CVC, pasaporte).
Las máscaras y el formato no deben revelar la validez de la cuenta («Si el correo electrónico está registrado...» - redacción neutral).
Idempotencia y retracción para sabmitas críticas (pago/apuesta).
13) Comportamiento de formas y rendimiento
Debauns de controles asíncronos (250-400 ms), la indicación visible «Chequeamos»....
No bloquee toda la pantalla por un solo campo; spinner/esqueleto local.
Batchite cambios DOM; animar sólo 'transformación/opacity'.
En los móviles - evitar «saltos» cuando aparezca el teclado (área segura, viewport meta).
14) Código de snippets
Máscara suave del teléfono (sin romper la inserción):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);
});
Suma: «crudo en el enfoque → formato en 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: upper-case y agrupación en 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 del sistema de diseño (ejemplo)
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) Especificidad de iGaming
Pagos/conclusiones: PAN/IBAN/amount con máscaras blandas; idempotencia estricta y ausencia de registros de campos sensibles; pistas sobre comisiones y plazos.
KYC: máscaras para fechas, números de pasaporte (sin filtrado «duro» - contabilidad de diferentes formatos), tamaño/tipo de archivo, vista previa.
Límites y juego responsable: cantidades/períodos claros (días/semanas/meses), helpers cercanos, contraste AAA.
Apuestas: entrada rápida de la suma (botones preestablecidos + campo), en el foco «crudo» número, en el blues el formato por la locala; no permitir «, «...../divisor doble.
17) Anti-patrones
Máscaras rígidas que prohíben caracteres/pegar válidos.
Caret de salto con formato automático; falta de selección/undo.
Placeholder en lugar del sello.
Auto-añadir moneda dentro de un valor (rompe el copipast).
Errores «en cada símbolo» sin debauns.
Formatos dependientes de la ubicación en el almacén (almacenar ISO/números).
La lógica de los números PAN/pasaporte y mostrar las razones «demasiado honestas» de la desviación.
18) Métricas y experimentos
Error rate por campos (antes/después de la máscara).
Formularios Time-to-Complete y reenvíos.
Proporción de inserciones fallidas (copipast) y «retrocesos» (undo).
CTR de consejos/ejemplos, proporción de autocompletados.
Abandon rate en el paso de pago/CUS.
19) QA-check-list
Entrada y caret
- La inserción desde el búfer no se rompe, los espacios/guiones se limpian correctamente.
- Caret sigue siendo predecible después del autoformato.
Local y formato
- Las cantidades permiten ', '/'.'; almacenamiento en unidades menores.
- Las fechas se parsean y validan; almacenamiento en ISO.
A11y
- Las etiquetas y 'aria-describedby' están conectadas; 'role =' alerta 'para los críticos.
- El contraste y los anillos de enfoque corresponden a AA.
- Los campos sensibles no están en caché o en la lógica.
- Idempotencia y retroceso en los pasos críticos.
UX
- Placeholder es un ejemplo, no una etiqueta; helper cerca.
- Las máscaras no impiden la impresión en móviles; teclados correctos ('inputmode').
20) Documentación en el sistema de diseño
Компоненты: `MaskedInput`, `MoneyInput`, `PhoneInput`, `OtpInput`, `IbanInput`.
Señales de máscaras (longitudes/patrones), reglas de caret/inserción, localización de números/fechas.
Gaids por privacidad (que no es lógico), por accesibilidad y por autoformato vs blues.
"Do/Don 't' con ejemplos reales y métricas antes/después.
Resumen breve
Las mascarillas y los formularios son buenos cuando aceleran la entrada, mantienen los datos limpios y no interfieren. Formatee cuidadosamente, normalice en la entrada, almacene en vistas estables, tenga en cuenta las localizaciones y la disponibilidad. Entonces los formularios se vuelven rápidos y comprensibles - especialmente en escenarios de pagos sensibles, KYC y apuestas.