Skip to content

Accordion Nuevo

El componente hp-accordion implementa el patrón WAI-ARIA Accordion, permitiendo crear interfaces de acordeón accesibles con múltiples paneles expandibles, navegación por teclado completa y soporte para modo de panel único.

Demostración

Sin estilos (solo base.css)

Así se ve hp-accordion usando únicamente @headless-primitives/utils/base.css. La navegación por teclado, aria-expanded y la visibilidad de paneles funcionan completamente.

¿Qué es Headless Primitives?

Una librería de componentes headless accesibles.

¿Por qué usarla?

Comportamiento y accesibilidad listos, tú pones los estilos.

Con estilos personalizados

¿Qué es Headless Primitives?

Es una librería de componentes headless que proveen la accesibilidad y comportamiento nativo.

¿Por qué usar acordeones?

Son perfectos para organizar contenido en secciones expandibles.

html
<hp-accordion class="faq-accordion">
  <hp-accordion-item class="faq-item" value="faq-1">
    <hp-accordion-trigger class="faq-trigger">
      ¿Qué es Headless Primitives?
      <span class="faq-icon">▼</span>
    </hp-accordion-trigger>
    <hp-accordion-content class="faq-content">
      <p>
        Es una librería de componentes headless que proveen la accesibilidad y comportamiento
        nativo, dejando total libertad creativa para el diseño visual.
      </p>
    </hp-accordion-content>
  </hp-accordion-item>

  <hp-accordion-item class="faq-item" value="faq-2">
    <hp-accordion-trigger class="faq-trigger">
      ¿Por qué usar acordeones?
      <span class="faq-icon">▼</span>
    </hp-accordion-trigger>
    <hp-accordion-content class="faq-content">
      <p>
        Los acordeones son perfectos para organizar contenido en secciones que pueden
        expandirse/contraerse, mejorando la experiencia de usuario en interfaces densas.
      </p>
    </hp-accordion-content>
  </hp-accordion-item>
</hp-accordion>
css
.faq-accordion {
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  overflow: hidden;
  background: white;
}

.faq-item {
  border-bottom: 1px solid #e2e8f0;
}

.faq-item:last-child {
  border-bottom: none;
}

.faq-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 16px 20px;
  background: #f8fafc;
  border: none;
  cursor: pointer;
  font-size: 15px;
  font-weight: 500;
  color: #1a202c;
  transition: background-color 0.2s;
}

.faq-trigger:hover {
  background: #f1f5f9;
}

.faq-trigger:focus {
  outline: 2px solid #3b82f6;
  outline-offset: -2px;
}

.faq-trigger[aria-expanded="true"] .faq-icon {
  transform: rotate(180deg);
}

.faq-content {
  padding: 20px;
  background: white;
  border-top: 1px solid #e2e8f0;
}

.faq-content[hidden] {
  display: none;
}

.faq-content p {
  margin: 0;
  color: #475569;
  line-height: 1.6;
}

.faq-icon {
  font-size: 12px;
  transition: transform 0.2s;
  color: #64748b;
}

Instalación

bash
pnpm add @headless-primitives/accordion
bash
npm install @headless-primitives/accordion
bash
yarn add @headless-primitives/accordion
bash
bun add @headless-primitives/accordion

Features

  • ⌨️ Navegación completa por teclado (flechas, Home, End).
  • ♿️ Relaciones ARIA gestionadas automáticamente (aria-expanded, aria-controls, aria-labelledby).
  • 🎨 Sin estilos visuales (Headless) — tú decides el diseño.
  • ⚡️ Modo single-panel para acordeones tipo exclusivo.
  • 🔒 Estado disabled propagable desde el root a todos los ítems.

Anatomía

html
<hp-accordion>
  <hp-accordion-item>
    <hp-accordion-trigger></hp-accordion-trigger>
    <hp-accordion-content></hp-accordion-content>
  </hp-accordion-item>
</hp-accordion>

API Reference

hp-accordion

Contenedor principal que coordina múltiples paneles de acordeón.

Atributos / Propiedades

Atributo / PropiedadTipoPor DefectoDescripción
single-panelbooleanfalseSi está presente, solo un panel puede estar abierto a la vez.
disabledbooleanfalseSi está presente, deshabilita todos los paneles del acordeón.

Eventos

EventoDetalleDescripción
hp-change{ open: boolean, value: string }Se dispara cuando cambia el estado de cualquier panel (bubbles).

hp-accordion-item

Panel individual dentro del acordeón.

Atributos / Propiedades

Atributo / PropiedadTipoPor DefectoDescripción
valuestringauto (UUID)Identificador único del panel.
openbooleanfalseSi está presente, el panel está expandido.
disabledbooleanfalseSi está presente, deshabilita solo este panel.

Eventos

EventoDetalleDescripción
hp-open{ value: string }Se dispara cuando el panel se expande.
hp-close{ value: string }Se dispara cuando el panel se contrae.
hp-change{ open: boolean, value: string }Se dispara en cualquier cambio de estado.

hp-accordion-trigger

Botón que controla la visibilidad del contenido del panel.

Atributos / Propiedades

Atributo / PropiedadTipoPor DefectoDescripción
disabledbooleanheredadoHeredado del contenedor hp-accordion-item.

Atributos ARIA gestionados automáticamente

  • role="button" — Asignado automáticamente si no se especifica.
  • aria-expanded — Sincronizado con el estado open del panel.
  • aria-controls — Referencia al ID del contenido.
  • aria-disabled — Sincronizado con el estado disabled.
  • tabindex="0" — Habilitado cuando no está deshabilitado.

hp-accordion-content

Panel de contenido que se muestra u oculta según el estado.

Atributos ARIA gestionados automáticamente

  • role="region" — Asignado automáticamente si no se especifica.
  • aria-labelledby — Referencia al ID del trigger.
  • data-state"open" | "closed" para estilizado CSS.
  • data-hp-panel — Presente siempre (usado por base.css).

Accesibilidad

Adhiere al patrón WAI-ARIA APG para Accordion.

TeclaAcción
Enter / SpaceActiva el trigger y abre/cierra el contenido.
ArrowDownMueve el foco al siguiente trigger.
ArrowUpMueve el foco al trigger anterior.
HomeMueve el foco al primer trigger.
EndMueve el foco al último trigger.

Ejemplos

Modo de Panel Único

html
<hp-accordion single-panel>
  <hp-accordion-item value="panel-1">
    <hp-accordion-trigger>Panel 1</hp-accordion-trigger>
    <hp-accordion-content>Contenido del panel 1...</hp-accordion-content>
  </hp-accordion-item>

  <hp-accordion-item value="panel-2">
    <hp-accordion-trigger>Panel 2</hp-accordion-trigger>
    <hp-accordion-content>Contenido del panel 2...</hp-accordion-content>
  </hp-accordion-item>
</hp-accordion>

Control Programático

javascript
const accordion = document.querySelector("hp-accordion");
const item = document.querySelector("hp-accordion-item");

// Abrir un panel específico
item.open = true;

// Escuchar cambios
item.addEventListener("hp-change", (e) => {
  console.log("Panel cambiado:", e.detail.open, e.detail.value);
});

// Cambiar a modo de panel único
accordion.singlePanel = true;

Paneles Deshabilitados

html
<hp-accordion>
  <hp-accordion-item value="enabled">
    <hp-accordion-trigger>Panel Habilitado</hp-accordion-trigger>
    <hp-accordion-content>Contenido accesible...</hp-accordion-content>
  </hp-accordion-item>

  <hp-accordion-item value="disabled" disabled>
    <hp-accordion-trigger>Panel Deshabilitado</hp-accordion-trigger>
    <hp-accordion-content>Contenido no accesible...</hp-accordion-content>
  </hp-accordion-item>
</hp-accordion>

Lanzado bajo la MIT License.