El cuadro de edición que abre diálogo y el foco que desapareció

Hace un tiempo estuve trabajando con un equipo de desarrolladores en un design system. Nos tocaba modificar un componente de calendario típico, donde el usuario podía hacer click sobre un campo de texto para ingresar una fecha, y al hacerlo, se desplegaría un modal con un selector de día, mes y año.

La idea, de primeras, parecía bastante sencilla. Yo acababa de entrar en el proyecto y no había visto los diseños que se habían hecho para este componente ni tampoco la documentación de accesibilidad, por lo que me dí de lleno con la página del componente en su Storybook. Agárrate los pantalones porque se viene idea revolucionaria:

cuando el usuario pulsaba la tecla Enter estando en el campo de edición, se abriría automáticamente un cuadro de diálogo para la selección de fechas. En código, sería algo así:

    <label for="dateInput">Seleccionar Fecha</label>
    <input type="text" id="dateInput" aria-haspopup="dialog" aria-expanded="false" aria-controls="dialogBox" />
    <div id="dialogBox" role="dialog"...></div>

Para empezar, utilizar aria-haspopup y aria-expanded en un campo de edición resultaba, cuanto menos, inusual. Pero más allá de eso, la verdadera complicación radicaba en que al presionar Enter, el diálogo no se enfocaba correctamente. A parte de que te estás comiendo el comportamiento de la tecla enter, estás haciendo que el usuario no se entere de que se ha abierto el selector.

Cuando vi esto me puse a flipar en colores, y eso que soy ciego total y no he visto colores en la vida. Propuse entonces, pensando en la idea de los skip links (enlaces que solo se visualizan con el foco de teclado) crear un botón al lado del cuadro de edición para que el usuario de teclado (atención, teclado, no lector de pantalla) pueda pulsar enter y espacio para que se abra el cuadro de diálogo con el selector de fechas.

A priori era una idea guay, y pensando en posibles confusiones, intenté dejar claro con código CSS que el botón de seleccionar fecha debe ser visible siempre que el usuario tenga el foco de teclado ahí. Mi ejemplo era algo parecido a lo siguiente:

<button class="select-date" aria-haspopup="Dialog" aria-label="Seleccionar Fecha" aria-expanded="true/false"> <svg del iconito del calendario que UX había creado/> </button>
.select-date {
  position: absolute;
  top: -40px; /* no se ve */
  left: 10px;
  background-color: #0073e6;
  color: white;
  padding: 8px 16px;
  transition: top 0.3s;
  text-decoration: none;
}

.select-date:focus {
  top: 10px; /* Lo pone en pantalla */
}

Esto estaba genial, de hecho cuando llegó la nueva revisión del componente mi intención era aprobarlo con un “wow, qué chulo!” han hecho un selector de fecha súper accesible y ahora el usuario de teclado ya no se va a perder. Pero esperaos un momento, que voy a consultarlo con mi compañero de visual, a ver que no sea que se rompa la UI o algo.

Cuál fue mi sorpresa cuando mi compañero me dijo que habían pasado de mi código de ejemplo. Cuando el usuario estaba en el cuadro de edición, todo guay, pero al hacer tab, el foco de teclado se iba al limbo perdido, más allá de los confines del espacio interestelar. el lector de pantalla, sin embargo y correctamente, anunciaba que el foco estaba en el botón Seleccionar Fecha.

Hablando con los compañeros desarrolladores, se ve que habían asumido que ese botón era invisible. Total, para qué vas a poner que se vea el botón, si es un usuario de teclado y lector de pantalla?

Ahí está el quid de la cuestión, alguien se había tomado la libertad de asumir que un usuario de teclado es usuario de lector de pantalla siempre, y ese ese es el error que nunca debemos cometer. Usuarios de teclado pueden ser muchos y muy variados, desde personas que tienen poca movilidad en la mano y no pueden usar el ratón, personas con baja visión, personas que utilicen dispositivos de control alternativos...

Conclusión sobre este caso

Hay que leer la documentación que te han dado. Si eres desarrollador y no sabes mucho de accesibilidad o estás aprendiendo, si te ponen un ejemplo para un botón que aparece visualmente con el foco, no pases. Tampoco hagas un cuadro de edición con un haspopup y un expanded, por favor.