Saltar al contenido principal

Pestañas

Las pestañas (tabs) permiten alternar entre varios paneles de información dentro de una misma ventana.

;

<div class="tabs">
  <div role="tablist">
    <button
      role="tab"
      aria-selected="true"
      aria-controls="panel-1"
      id="tab-1"
      tabindex="0"
    >
      Panel 1
    </button>
    <button
      role="tab"
      aria-selected="false"
      aria-controls="panel-2"
      id="tab-2"
      tabindex="-1"
    >
      Panel 2
    </button>
    <button
      role="tab"
      aria-selected="false"
      aria-controls="panel-3"
      id="tab-3"
      tabindex="-1"
    >
      Panel 3
    </button>
  </div>
  <div id="panel-1" role="tabpanel" tabindex="0" aria-labelledby="tab-1">
    <p>Contenido del panel #1</p>
  </div>
  <div id="panel-2" role="tabpanel" tabindex="0" aria-labelledby="tab-2" hidden>
    <p>Contenido del panel #2</p>
  </div>
  <div id="panel-3" role="tabpanel" tabindex="0" aria-labelledby="tab-3" hidden>
    <p>Contenido del panel #3</p>
  </div>
</div>
// Selecciona los botones de los paneles
const tabList = document.querySelector('[role="tablist"]');
const tabs = tabList.querySelectorAll(':scope > [role="tab"]');

// Añade un evento para cada pestaña
tabs.forEach((tab) => {
  tab.addEventListener("click", changeTabs);
});

// Habilita la navegación con flechas entre pestañas
let tabFocus = 0;
tabList.addEventListener("keydown", (e) => {
  if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
    tabs[tabFocus].setAttribute("tabindex", -1);
    if (e.key === "ArrowRight") {
      tabFocus++;
      if (tabFocus >= tabs.length) {
        tabFocus = 0;
      }
    } else if (e.key === "ArrowLeft") {
      tabFocus--;
      if (tabFocus < 0) {
        tabFocus = tabs.length - 1;
      }
    }
    tabs[tabFocus].setAttribute("tabindex", 0);
    tabs[tabFocus].focus();
  }
});

// Configura la pestaña seleccionada y muestra el panel
function changeTabs(e) {
  const targetTab = e.target;
  const tabList = targetTab.parentNode;
  const tabGroup = tabList.parentNode;
  tabList
    .querySelectorAll(':scope > [aria-selected="true"]')
    .forEach((t) => t.setAttribute("aria-selected", false));
  targetTab.setAttribute("aria-selected", true);
  tabGroup
    .querySelectorAll(':scope > [role="tabpanel"]')
    .forEach((p) => p.setAttribute("hidden", true));
  tabGroup
    .querySelector(`#${targetTab.getAttribute("aria-controls")}`)
    .removeAttribute("hidden");
}

Atributos ARIA

  • El elemento que contiene las pestañas tiene el rol tablist.
  • Cada pestaña tiene el rol tab.
  • El estado aria-selected indica si la pestaña está activa o no mediante los valores true o false.
  • Cada panel tiene el rol tabpanel y está asociado con su pestaña correspondiente mediante la propiedad aria-labelledby.

Interacción con teclado

  • Tab mueve el foco a la pestaña activa.
  • Flecha izquierda mueve el foco a la pestaña anterior, o a la última si el foco está en la primera.
  • Flecha derecha mueve el foco a la siguiente pestaña, o a la primera si el foco está en la última.
  • Intro o Espacio activa la pestaña si no se ha activado automáticamente al enfocarla.