Skip to main content

La mayoría de campos de código de verificación son seis inputs, uno por dígito. Funcionan si escribes el código a mano, carácter a carácter. En cuanto pegas el código o dejas que el móvil lo rellene, fallan.

Al diseñar @teselia/otp, el segundo componente de Teselia, descarté ese modelo desde el principio.

Los problemas de seis campos

  • El lector de pantalla anuncia seis campos sin nombre en lugar de uno con su etiqueta.
  • Al pegar, el código entero cae en la primera casilla, salvo que alguien escriba código frágil para repartirlo.
  • El móvil, cuando te sugiere el código que acaba de llegar, rellena un único campo. Con seis, a menudo no rellena ninguno.
  • El script tiene que mover el foco en cada tecla, y cada implementación resuelve a su manera el borrado entre casillas.

Lo del autocompletado afecta al cumplimiento. El criterio 3.3.8 de WCAG 2.2, Autenticación accesible, pide que nadie tenga que transcribir un código carácter a carácter para identificarse. Si no puedes pegarlo ni autocompletarlo, el campo no cumple.

Un campo real debajo de las casillas

El componente tiene un único <input> con el código completo. Las casillas que ves son un dibujo: elementos que los lectores de pantalla ignoran y que copian el valor del campo, un carácter en cada una. Encima coloqué el campo real con el texto y el cursor transparentes, y ese campo recibe el ratón y el teclado.

Para que se comporte como casillas, cuando el cursor cae en una casilla llena, el componente selecciona ese carácter. Si escribes, lo sustituyes, y el código nunca pasa de su longitud.

La prueba que hice antes de escribir código

Los Web Components guardan su contenido en un Shadow DOM, y yo no sabía si el iPhone ofrecería el código recibido para un campo que vive ahí dentro. Si no lo hacía, el componente no tenía sentido.

Preparé una página de prueba y me envié un correo con un código. El teclado del iPhone lo sugirió en los tres campos de la página, incluido el del componente. Con esa respuesta, empecé a escribir el resto.

Detalles que aparecieron al probar

  • maxlength estropeaba el pegado. El navegador recorta el texto antes de que el componente lo limpie, así que al pegar 123 456 el espacio ocupaba un hueco y perdías el último dígito. Quité maxlength, y ahora el componente recorta después de quitar espacios y guiones. Un test pega a través del portapapeles real y falla si alguien lo vuelve a poner.
  • Dígitos de otras escrituras. Los teclados japonés y chino pueden escribir dígitos de ancho completo, y la escritura árabe tiene sus propios dígitos. El componente convierte todos a 0-9.
  • Una flecha mantenida. En Brave, si mantenías pulsada una flecha, el cursor avanzaba pero la casilla activa se quedaba quieta hasta que la soltabas. Lo encontré en las pruebas a mano y ya lo he corregido.
  • Teclados con predicción. Si el componente reescribe el campo mientras el teclado del móvil compone una palabra, rompe el teclado. Ahora espera a que termine.

Envío automático, desactivado por defecto

Muchos campos de este tipo envían el formulario al escribir el último dígito. Resulta cómodo, pero te cambia de página sin que lo pidas, y WCAG 2.2 exige avisar antes de un cambio así.

Teselia lo trae desactivado. Si lo activas con el atributo autosubmit, aparece bajo las casillas un aviso visible de que el código se enviará al escribir el último dígito. El mismo aviso forma parte de la descripción del campo, y los lectores de pantalla también lo leen.

Lo que no salió como quería

El gestor de contraseñas que probé rellenaba códigos en campos de tipo contraseña, y en un campo de texto no. Podría haber cambiado el tipo del campo, pero entonces verías puntos en lugar del código, los lectores de pantalla leerían caracteres ocultos y el navegador te ofrecería guardarlo como contraseña. Lo dejé como campo de texto. Puedes copiar el código desde el gestor y pegarlo en un paso.

El documento de diseño explica el razonamiento completo, y la documentación incluye una demo.

Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.