widget-keyboard-focusable

Los widgets deberían ser alcanzables con el teclado

manualWCAG 2.1.1 (A)confianza: mediumgravedad: seriousoperable

Marca un elemento con rol de widget que no puede recibir el foco o está fuera del orden de tabulación, y un widget compuesto sin ninguna parada de tabulación, para revisión manual.

Ámbito de aplicación. Elementos que la página muestra con aria-activedescendant, y aquellos cuyo rol, del atributo role o de los ElementInternals de un elemento personalizado, es un widget que opera el usuario:

  • widgets simples: button, link, checkbox, switch, radio, slider, spinbutton, textbox, searchbox, combobox;
  • widgets compuestos: grid, treegrid, listbox, menu, menubar, tree, tablist, toolbar, radiogroup.

Se dejan fuera:

  • un elemento fuera del árbol de accesibilidad (aria-hidden="true"), o deshabilitado (disabled, o aria-disabled="true" en él o en un ancestro): no ofrece nada que operar;
  • un widget dentro de un widget compuesto, o dentro de un elemento que puede recibir el foco y cuyo aria-activedescendant apunta a un elemento (por id, o asignado desde un script como ariaActiveDescendantElement; un atributo vacío no apunta a nada): el widget compuesto mueve el foco entre sus elementos (un tabindex itinerante, o roving tabindex) o lo conserva y apunta al activo, así que se evalúa en su lugar el elemento exterior (en un submenú, su menubar);
  • un elemento con un onclick en línea, o un listener de clic que vio el hook de listeners (listenerHookScript), que evalúa click-handler-keyboard-operable.

Resultado esperado. Un usuario de teclado puede llegar al widget con Tab (WCAG 2.1.1). Solo se lee la enfocabilidad del marcado: un script puede mover el foco o gestionar las teclas de formas que el marcado no muestra, así que un hallazgo es una pregunta, nunca un fallo.

  • Un widget simple que está en el orden de tabulación, o que contiene un elemento que lo está, pasa.
  • Un widget simple que no puede recibir el foco, y no contiene nada que pueda: cantTell (WIDGET_NOT_FOCUSABLE). Comprueba que un usuario de teclado puede llegar a él, o a lo que hace, de otra forma.
  • Un widget simple que solo recibe el foco desde un script (tabindex="-1"): cantTell (WIDGET_NOT_IN_TAB_ORDER). Tab nunca llega a él; compruebe que un script le mueve el foco, o que lo que hace se ofrece en otro sitio.
  • Un widget compuesto pasa cuando está en el orden de tabulación (con aria-activedescendant apuntando a su elemento activo, o no) o contiene un elemento que lo está. Uno que ningún otro elemento nombra en aria-controls o aria-owns (una ventana emergente abierta por un botón o un combobox recibe el foco de él) y que no tiene ninguna de las dos cosas: cantTell (COMPOSITE_NO_TAB_STOP).
  • Un elemento de cualquier rol que lleva aria-activedescendant y no puede recibir el foco: cantTell (ACTIVEDESCENDANT_HOST_NOT_FOCUSABLE). El elemento activo solo se anuncia mientras ese elemento tiene el foco. Un elemento así no gestiona el foco de los widgets que contiene, así que estos se evalúan por sí mismos.

Qué informa un hallazgo.

  • role: el rol del elemento.
  • focusable: si el propio elemento puede recibir el foco.
  • scriptFocusable: en un widget compuesto, si algún elemento dentro de él recibe el foco desde un script (tabindex="-1").

Estos campos de data.details ayudan a leer y reproducir un hallazgo. Salvo reasonCode y los pocos campos que Esquema de salida indica como estables, no son un contrato estable: un campo puede cambiar de nombre o desaparecer en una versión menor, así que no construyas sobre ellos.

Ejemplos

pass
<div role="button" tabindex="0">Save</div>

El botón personalizado está en el orden de tabulación.

can't tell
<div role="button">Save</div>

El elemento dice que es un botón, pero Tab nunca llega a él. Una persona comprueba que un usuario de teclado puede llegar a él, o a lo que hace, de otra forma.

Cómo comprobarlo

Cuando esta regla no puede decidir, informa cantTell y deja la pregunta a una persona. Cada pregunta que puede plantear aparece aquí bajo su código de motivo, con los pasos para responderla. Un hallazgo lleva los mismos pasos en howToCheck, en el idioma del análisis. Consulta Esquema de salida.

ACTIVEDESCENDANT_HOST_NOT_FOCUSABLE

  1. Localizar el elemento que indica el informe; usa aria-activedescendant para apuntar a su elemento activo.
  2. Usando solo el teclado, abrir o alcanzar el widget (por ejemplo, escribir en su cuadro de búsqueda) y observar si es ese elemento, y no otro, el que recibe el foco.
  3. Pulsar las teclas de flecha con un lector de pantalla en marcha y escuchar si se anuncia cada elemento activo.
  4. Si no se puede llegar a los elementos de esta forma, comprobar si las mismas opciones se pueden elegir de otra forma solo con el teclado, por ejemplo escribiendo el valor en un campo de texto. Solo cuenta si todas las opciones están disponibles así y un lector de pantalla las anuncia.

Se cumple. El elemento recibe el foco y el lector de pantalla anuncia cada elemento activo al mover las teclas de flecha, o las mismas opciones se pueden elegir de otra forma solo con el teclado y el lector de pantalla las anuncia.

No se cumple. El elemento no puede recibir el foco, así que moverse por los elementos no anuncia nada o no se puede llegar a ellos, y las opciones no se pueden elegir de otra forma con el teclado, lo que incumple WCAG 2.1.1.

COMPOSITE_NO_TAB_STOP

  1. Localizar el widget que indica el informe (un menú, un cuadro de lista, una lista de pestañas, una barra de herramientas, una cuadrícula o un árbol).
  2. Hacer clic justo antes de él, pulsar Tab y observar si el foco entra en él o en uno de sus elementos.
  3. Si es una ventana emergente, abrirla con el teclado desde su botón y ver si el foco pasa a su interior.
  4. Una vez dentro, comprobar que las teclas de flecha se mueven entre los elementos.
  5. Si el foco nunca entra, comprobar si lo que hace el widget se puede hacer de otra forma solo con el teclado, por ejemplo las mismas opciones ofrecidas como enlaces o botones en otra parte de la página. Solo cuenta si todas las opciones del widget están disponibles así.

Se cumple. Tab (o el botón que lo abre) pone el foco en el widget y las teclas de flecha se mueven entre sus elementos, o todo lo que hacen sus elementos se puede hacer de otra forma solo con el teclado.

No se cumple. El foco nunca entra en el widget ni en sus elementos con el teclado, y lo que hacen no se puede hacer de otra forma con el teclado, lo que incumple WCAG 2.1.1.

WIDGET_NOT_FOCUSABLE

  1. Localizar el widget que indica el informe y anotar lo que hace al hacer clic o al tocarlo.
  2. Hacer clic justo antes de él, pulsar Tab y observar si el foco llega alguna vez a él.
  3. Si nunca recibe el foco, buscar otro control al que se llegue con el teclado y que haga lo mismo.
  4. Si el elemento no hace nada, puede que su rol sea erróneo; anotarlo en su lugar.

Se cumple. El widget recibe el foco del teclado y funciona con el teclado, u otro control alcanzable con el teclado ofrece la misma función.

No se cumple. El widget no se puede alcanzar ni usar con el teclado y su función no se ofrece en otro lugar, lo que incumple WCAG 2.1.1 (F42).

WIDGET_NOT_IN_TAB_ORDER

  1. Localizar el widget que indica el informe y anotar cuándo aparece (por ejemplo, cuando se abre un menú o un diálogo).
  2. Usar solo el teclado para abrir o alcanzar esa parte de la página, y observar si un script lleva el foco al widget, o si las teclas de flecha llegan a él.
  3. Si el foco nunca llega a él, buscar otro control alcanzable con el teclado que haga lo mismo.

Se cumple. Un script o las teclas de flecha llevan el foco al widget cuando hace falta, o su función se ofrece en otro lugar.

No se cumple. Ni Tab ni las teclas de flecha llegan nunca al widget y nada más ofrece su función, lo que incumple WCAG 2.1.1.

Ver código fuente