7.4: Menús de árbol
- Page ID
- 152652
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)Los menús de árbol a menudo tienen la misma estructura HTML subyacente que una barra de menús, pero en lugar de estar dispuestos en un diseño horizontal, tienden a estar dispuestos verticalmente.
Funciones, estados y propiedades de WAI-ARIA utilizados en un menú de árbol
- tabindex = [0 | -1]
- aria-labelledby = [instrucción div id | título div id]
- aria-oculto = [verdadero | falso]
- role = “árbol”
- role = “treeitem”
- role = “presentación”
- aria-level = [número de ULs padres]
- aria-setsize = [número de LIs en un nivel]
- aria-posinset = [posición de cada LI en un conjunto]
- aria-expandido = [true | false]
- aria-selected = [true | false]
El siguiente JSFiddle presenta un típico widget de menú de árbol con algunos submenús. Revise el marcado JavaScript y HTML. Pruebe el menú de árbol presentado bajo la pestaña Resultado con ChromeVox para entender cómo funciona sin agregar ninguna característica de accesibilidad. Puedes trabajar en JSFiddle haciendo clic en “Editar en JSFiddle” en la parte superior, a la derecha, copiando el código de Accesibilidad/Wai-Aria que se describe a continuación para corregir la accesibilidad del menú del árbol antes de completar la Actividad 13 en la página que sigue.
Primero, defina instrucciones sobre el uso del menú de árbol con un teclado.
Dentro de la función init ()
agregue el enfoque del teclado al contenedor del árbol aplicándole tabindex="0"
, y etiquete el contenedor con las instrucciones creadas anteriormente, que es leído por los lectores de pantalla cuando el menú recibe inicialmente el foco.
Dentro de la función init ()
, oculte las instrucciones <div>de los lectores de pantalla por defecto configurando
aria-hidden="true”
cuando se inicializa el menú del árbol.
Dentro de la función init ()
reemplace la semántica de lista desordenada con semántica de menú de árbol usando role="tree”
, y dale un título usando aria-labelledby
para hacer referencia al título definido en las opciones predeterminadas.
Dentro de la función init ()
, defina los elementos del menú con role="treeitem”
, elimine todo el acceso al teclado por defecto con tabindex=” -1"
, establezca el número de niveles en el árbol en función del número de ULs principales con aria-level= [número de ULs]
, establezca el número de elementos del árbol en un nivel dado con aria-setsize= "[número de LIs en un UL]”
, y finalmente definir la posición de cada elemento del árbol dentro de un nivel usando aria-posinset= "[índice LI hijo]”
.
Dentro de la función init ()
, si un elemento de árbol tiene un submenú UL que ha sido abierto, establezca aria-expanded="true”
, de lo contrario establecer aria-expanded="false”
.
Dentro de la función init ()
, para cada elemento de árbol use el texto del elemento span
asociado como su etiqueta. Para garantizar que tanto la etiqueta como el contenido del elemento span
no sean leídos, asigne role="presentation”
al span
.
Dentro de la función init ()
, donde se utiliza la funcionalidad onclick
del mouse, se proporciona una funcionalidad keydown
equivalente, aquí haciendo referencia a la función OnKeyDown
, que se muestra a continuación, que define las teclas para operar el menú.
Dentro de la función init ()
, justo después de agregar operabilidad keydown
, haga que el primer elemento del menú del árbol sea enfocable agregando tabindex="0"
a la primera li
.
Dentro de la función selectItem ()
, configura un tabindex errante, mientras que al mismo tiempo aplica aria-selected= [true | false]
cuando los elementos del árbol reciben o pierden el foco.
En la función ToggleSubMenu ()
, anuncie el estado de los submenús al lector de pantalla alternando el atributo aria-expanded= [true | false]
cuando se abre o cierra un menú.
Adición de operabilidad del teclado
Al igual que la barra de menú descrita en la actividad anterior, la operabilidad del teclado para un menú de árbol puede ser compleja, con varias operaciones que utilizan múltiples pulsaciones de teclas para realizar la misma función. El W3C describe el funcionamiento potencial del teclado en las prácticas de autoría de WAI-ARIA 1.1, reproducidas a continuación.
Interacción con el teclado del menú
Para un árbol orientado verticalmente:
- Cuando un árbol de selección única recibe foco:
- Si ninguno de los nodos se selecciona antes de que el árbol reciba el foco, el enfoque se establece en el primer nodo.
- Si se selecciona un nodo antes de que el árbol reciba el foco, el enfoque se establece en el nodo seleccionado.
- Cuando un árbol de selección múltiple recibe foco:
- Si ninguno de los nodos se selecciona antes de que el árbol reciba el foco, el enfoque se establece en el primer nodo.
- Si se seleccionan uno o más nodos antes de que el árbol reciba el foco, el enfoque se establece en el primer nodo seleccionado.
- Flecha derecha:
- Cuando el foco está en un nodo cerrado, abre el nodo; el enfoque no se mueve.
- Cuando el enfoque está en un nodo abierto, mueve el enfoque al primer nodo hijo.
- Cuando el foco está en un nodo final, no hace nada.
- Flecha izquierda:
- Cuando el foco está en un nodo abierto, cierra el nodo.
- Cuando el foco está en un nodo hijo que también es un nodo final o un nodo cerrado, mueve el foco a su nodo padre.
- Cuando el foco está en un nodo raíz que también es un nodo final o un nodo cerrado, no hace nada.
- Flecha abajo: Mueve el foco al siguiente nodo que es enfocable sin abrir o cerrar un nodo.
- Flecha arriba: Mueve el foco al nodo anterior que es enfocable sin abrir o cerrar un nodo.
- Inicio: Mueve el foco al primer nodo del árbol sin abrir o cerrar un nodo.
- Fin: Mueve el foco al último nodo del árbol que es enfocable sin abrir un nodo.
- Enter: Activa un nodo, es decir, realiza su acción por defecto. Para los nodos padre, una posible acción predeterminada es abrir o cerrar el nodo. En árboles de selección única donde la selección no sigue el enfoque (vea la nota a continuación), la acción predeterminada suele ser seleccionar el nodo enfocado.
- Se recomienda escribir adelante para todos los árboles, especialmente para árboles con más de 7 nodos de raíz:
- Escriba un carácter: el enfoque se mueve al siguiente nodo con un nombre que comienza con el carácter escrito.
- Escriba varios caracteres en sucesión rápida: el enfoque se mueve al siguiente nodo con un nombre que comienza con la cadena de caracteres mecanografiada.
- * (Opcional): Expande todos los hermanos que estén en el mismo nivel que el nodo actual.
- Selección en árboles de selección múltiple: Los autores pueden implementar cualquiera de dos modelos de interacción para admitir la selección múltiple: un modelo recomendado que no requiere que el usuario mantenga presionada una tecla modificadora, como Mayús o Ctrl, mientras navega por la lista o un modelo alternativo que requiera teclas modificadoras que se llevará a cabo mientras navega con el fin de evitar perder estados de selección.
- Modelo de selección recomendado: no es necesario mantener pulsado una tecla modificadora mientras se mueve el enfoque:
- Espacio: Activa el estado de selección del nodo enfocado.
- Mayús + Flecha abajo (Opcional): Mueve el enfoque y alterna el estado de selección del siguiente nodo.
- Mayús + Flecha arriba (Opcional): Mueve el enfoque y alterna el estado de selección del nodo anterior.
- Shift + Space (Opcional): Selecciona nodos contiguos desde el último nodo seleccionado hasta el nodo actual.
- Ctrl + Mayús + Inicio (Opcional): Selecciona el nodo con foco y todos los nodos hasta el primer nodo.
- Ctrl + Mayús + Fin (Opcional): Selecciona el nodo con foco y todos los nodos hasta el último nodo.
- Ctrl + A (Opcional): Selecciona todos los nodos del árbol. Opcionalmente, si se seleccionan todos los nodos, también puede deseleccionar todos los nodos.
- Modelo de selección alternativo: mover el enfoque sin mantener presionado el modificador Mayús o Ctrl deselecciona todos los nodos seleccionados excepto el nodo enfocado:
- Mayús + Flecha abajo: Mueve el enfoque y alterna el estado de selección del siguiente nodo.
- Mayús + Flecha arriba: Mueve el foco y alterna el estado de selección del nodo anterior.
- Ctrl + Flecha abajo: Sin cambiar el estado de selección, mueve el foco al siguiente nodo.
- Ctrl + Flecha arriba: Sin cambiar el estado de selección, mueve el foco al nodo anterior.
- Ctrl + Espacio: Activa el estado de selección del nodo enfocado.
- Shift + Space (Opcional): Selecciona los nodos contiguos del nodo seleccionado más recientemente al nodo actual.
- Ctrl + Mayús + Inicio (Opcional): Selecciona el nodo con foco y todos los nodos hasta el primer nodo.
- Ctrl + Mayús + Fin (Opcional): Selecciona el nodo con foco y todos los nodos hasta el último nodo.
- Ctrl + A (Opcional): Selecciona todos los nodos del árbol. Opcionalmente, si se seleccionan todos los nodos, también puede deseleccionar todos los nodos.
- Modelo de selección recomendado: no es necesario mantener pulsado una tecla modificadora mientras se mueve el enfoque:
- El enfoque DOM (el elemento activo) es funcionalmente distinto del estado seleccionado. Para más detalles, consulte esta descripción de las diferencias entre enfoque y selección.
- El rol de
árbol
soporta la propiedad aria-activedescendant, que proporciona una alternativa para mover el enfoque DOM entre los elementostreeitem
al implementar la navegación por teclado. Para obtener más detalles, consulte Gestión del enfoque en compuestos usando aria-activedescendant. - En un árbol de selección única, el enfoque móvil puede opcionalmente deseleccionar el nodo seleccionado previamente y seleccionar el nodo recién enfocado. Este modelo de selección se conoce como “la selección sigue el enfoque”. Tener el enfoque de seguimiento de selección puede ser muy útil en algunas circunstancias y puede degradar severamente la accesibilidad en otras. Para obtener orientación adicional, consulte Decidir cuándo realizar la selección Seguir el enfoque automáticamente.
- Si seleccionar o desseleccionar todos los nodos es una función importante, implementar controles separados para estas acciones, como los botones para “Seleccionar todo” y “Deseleccionar todo”, mejora significativamente la accesibilidad.
- Si los nodos de un árbol están dispuestos horizontalmente:
- Flecha abajo funciona como Flecha derecha se describe arriba y viceversa.
- Flecha arriba funciona como Flecha izquierda se describe arriba y viceversa.
Fuente: Prácticas de autoría de WAI-ARIA 1.1
Para el menú de árbol creado aquí, hemos agregado la operabilidad básica del teclado. La operación del teclado incluye: Arriba y Abajo, y Flechas Izquierda y Derecha para navegar dentro del árbol, y las teclas Entrar o Barra espaciadora para alternar los submenús abiertos o cerrados. La tecla Tab por defecto entra y sale del menú de árbol y no necesita definirse como parte de la operabilidad del teclado del menú de árbol.
Menú de árbol accesible en acción
Mira el siguiente video que muestra ChromeVox interactuando con un menú de árbol. La tecla Tab se utiliza para navegar al menú del árbol, al primer elemento del árbol y para salir del menú del árbol. Las flechas Arriba y Abajo se utilizan para moverse entre los elementos del árbol. La barra espaciadora o la tecla Intro se utilizan para expandir y contraer un elemento de árbol con un submenú. Cuando se abre un submenú, el enfoque se mueve al primer elemento del árbol del menú. Apunta a que opere el menú de árbol que actualices en la Actividad 13 y se anuncie como el del video.
Video: Menú Árbol Accesible