Acordeón
FancyAccordion es un acordeón único y reutilizable, construido para
funcionar con cualquier diseño visual (skin) que necesite un acordeón en
las plantillas de Fancy Etch — el mismo contrato de markup y el mismo
script controlan tanto una lista de FAQ simple, como un acordeón numerado a
ancho completo, como una vitrina con reproducción automática, con solo un
prop skin (y el CSS) cambiando entre ellos.

Anatomía
Dos componentes: FancyAccordion (el contenedor) y FancyAccordionItem
(un par pregunta/respuesta, usado dentro de su slot items — una instancia
por item).
El script se ata a un pequeño conjunto de atributos data-* en vez de
clases, así que cualquier skin puede re-diseñarse libremente sin tocar el
comportamiento:
| Atributo | Dónde | Propósito |
|---|---|---|
data-fe-acc | Raíz | Marca la instancia del acordeón. Las opciones (allow-multiple, open-first, autoplay, autoplay-interval) se leen de atributos planos en este mismo elemento. |
data-fe-acc-item | Envoltorio de cada item | Un par pregunta/respuesta. |
data-fe-acc-button | Dentro de un heading | El botón disclosure — debe vivir dentro de un <h2>–<h6> para cumplir el patrón APG. |
data-fe-acc-panel | Hermano del heading del botón | El panel de respuesta — animado con una transición CSS pura de grid-rows, sin medir alturas por JS. |
Props
FancyAccordion
| Prop | Tipo | Default | Notas |
|---|---|---|---|
label | string | "Accordion" | Nombre accesible de todo el acordeón (aria-label). |
openFirst | boolean | true | Abre el primer item al cargar. |
allowMultiple | boolean | false | Permite que más de un item quede abierto a la vez. |
syncId | string | "" | Id opcional de grupo exclusivo — ver Grupos de sincronización. Normalmente no hace falta; envolver los acordeones basta. |
skin | select | "underline" | Diseño visual — underline, bordered, numbered, minimal. Ver Skins más abajo. |
indicator | select | "arrow" | Forma del glyph del botón — arrow, angle, dot. Independiente del skin: cualquier indicador combina con cualquier skin. |
indicatorBg | select | "filled" | Si el indicador va dentro de una insignia con color/borde (filled) o suelto (bare). |
showNumber | boolean | true | Muestra el número automático del item. Solo visible en el editor mientras skin es numbered — una elección simple de sí/no, no depende del ancho de pantalla. |
autoplay | boolean | false | Activa el ciclo automático — ver Autoplay más abajo. |
| (Opciones de autoplay) | condition | visible cuando autoplay está activo | |
autoplayInterval | string | "6" | Segundos entre avances automáticos. Solo visible en el editor mientras autoplay está activo. Activar/desactivar autoplay/autoplayInterval surte efecto de inmediato en el builder — no hace falta recargar. |
pauseHover | boolean | true | Pausa el ciclo mientras el puntero está encima. Off = sigue corriendo en hover; un clic manual igual pausa, y al salir reanuda. Ver Autoplay. |
disableOnMobile | boolean | false | No corre el autoplay por debajo del breakpoint de tablet (max-width: 767px). Se re-evalúa en vivo al cruzar el breakpoint. |
| Progress bar (grupo) | — | — | Aspecto de la barra (agrupado en el panel). |
progressBar.orientation | select | "vertical" | vertical (rail en el borde) u horizontal (barra inferior). El skin numbered es siempre horizontal. Ver Orientación. |
progressBar.color | string | "var(--primary)" | Color del relleno de la barra, por instancia — color o variable CSS. |
progressBar.width | string | "3px" | Grosor de la barra. |
FancyAccordionItem
| Prop | Tipo | Default | Notas |
|---|---|---|---|
heading | string | "I am a heading" | El texto de la pregunta. |
headingLevel | select | "h3" | h2–h6 — elige según el esquema de headings de la página que lo rodea. |
El contenido de la respuesta va en el slot content del item, no en una
prop — coloca cualquier contenido enriquecido (párrafos, listas, imágenes)
como hijos del slot.
Skins
Cuatro diseños visuales disponibles hoy, todos construidos sobre los mismos
dos componentes — sin wrapper, sin un componente separado por diseño.
skin, indicator e indicatorBg son elecciones independientes; combina
cualquier indicador con cualquier skin.
| Skin | Descripción |
|---|---|
underline | Por defecto — subrayado deslizante bajo el heading del botón, icono en insignia redondeada. |
bordered | Items en tarjeta con borde, subrayado de ancho fijo en el botón. Combina bien con indicator="dot". |
numbered | Diseño a ancho completo — numeración automática 01, 02... vía un contador CSS, sin prop por item. Activa/desactiva la columna del número con el prop showNumber (solo aparece en el editor con este skin). |
minimal | Botón sin icono, solo heading — el look más limpio, y el que inspiró el riel de progreso del autoplay, aunque puedes usarlo con o sin autoplay. |
El CSS completo de cada skin vive junto en un solo lugar del Style Manager: selecciona una instancia de FancyAccordion, entra a su editor de elemento, y la clase .fe-acc--skins muestra una pestaña por cada skin (separadas por comentarios /*# Skin: Nombre #*/ dentro de ella) — no hace falta buscar entre toda la lista de clases para encontrar la que quieres.
Grupos de sincronización
Dos o más acordeones pueden actuar como un grupo exclusivo: abrir un item en cualquiera cierra lo que esté abierto en los demás, así que solo hay uno abierto en todo el grupo. El caso típico es un FAQ partido en columnas.
Hay dos formas de formar un grupo — usa la que encaje con tu layout:
- Envolverlos (sin id). Pon los acordeones dentro de un elemento con
data-fe-acc-group. Todo lo que esté dentro de ese wrapper es un grupo. Es lo más simple y con scope natural — otro wrapper en otro sitio es su propio grupo independiente. - Darles un
syncId. Los acordeones con el mismo Sync group id forman un grupo aunque estén dispersos por la página. Úsalo cuando no sean hermanos bajo un mismo wrapper.
Puedes usar una u otra (o ambas); un acordeón sin wrapper y sin syncId queda
independiente. Los pares se buscan en vivo, así que acordeones añadidos después
también se unen. Cada acordeón mantiene su propio comportamiento de teclado — el
grupo solo coordina qué item está abierto.
<!-- Sin id: el wrapper es el grupo -->
<div data-fe-acc-group class="faq-columns">
<div class="fe-acc" data-fe-acc>…</div>
<div class="fe-acc" data-fe-acc>…</div>
</div>
Accesibilidad
Sigue por completo el patrón ARIA de Accordion:
- El disparador es un
<button>real dentro de un heading (<h2>–<h6>), conaria-expandedyaria-controlssincronizados automáticamente. - El panel tiene
role="region"yaria-labelledbyapuntando de vuelta a su botón. - Los paneles cerrados se marcan
inert(no solo ocultos visualmente) — se eliminan tanto del orden de tabulación como del árbol de accesibilidad mientras se animan hacia el cierre, no solo después de que termina la transición. - Teclado: ↓ / ↑ mueven el foco entre botones (con vuelta al principio/final), Home / End saltan al primer/último botón, Esc cierra el item abierto actual y devuelve el foco a su botón.
- Todas las transiciones respetan
prefers-reduced-motion.
Variables CSS
Cada ajuste visual vive como una propiedad personalizada en la clase raíz
.fe-acc — ábrela en el Style Manager y retematiza una instancia sin tocar
un solo selector anidado. Un skin (como el diseño numerado a ancho
completo) puede sobreescribir cualquiera de estas en vez de redeclarar
reglas.
| Variable | Default | Controla |
|---|---|---|
--fe-acc-gap | 0 | Espacio vertical entre items. |
--fe-acc-border-color | var(--base-light) | Color del divisor entre items. |
--fe-acc-accent | var(--primary) | Color de acento del skin (ej. un subrayado deslizante). |
--fe-acc-icon-size | 2.2rem | Tamaño de la insignia del icono del botón. |
--fe-acc-icon-radius | 0.625rem | Radio de esquina de la insignia del icono. |
--fe-acc-icon-color | var(--primary) | Color del icono, estado cerrado. |
--fe-acc-icon-bg | var(--base-ultra-light) | Fondo de la insignia del icono, estado cerrado. |
--fe-acc-icon-color-open | var(--white) | Color del icono, estado abierto. |
--fe-acc-icon-bg-open | var(--primary) | Fondo de la insignia del icono, estado abierto. |
--fe-acc-icon-glyph-size | 0.8em | Tamaño del glyph del indicador en sí, relativo a su insignia (más pequeño que la insignia, a propósito, para un look moderno y minimal). |
--fe-acc-icon-glyph | SVG de flecha | La forma del glyph, como mask-image. Así es como indicator cambia de forma sin tocar el markup — el glyph no es un <svg> inline, es una máscara sobre el elemento del icono. |
--fe-acc-heading-size | var(--h3) | Tamaño de fuente del texto del botón. |
--fe-acc-content-gap | var(--content-gap) | Espacio entre filas dentro del panel de respuesta. |
--fe-acc-duration / --fe-acc-ease | 0.5s / ease | Timing de la transición de abrir/cerrar. |
--fe-acc-progress-color | var(--primary) | Relleno de la barra de progreso del autoplay. |
--fe-acc-progress-bg | var(--base-light) | Riel de la barra de progreso del autoplay. |
--fe-acc-progress-width | 4px | Grosor de la barra de progreso. |
--fe-acc-progress-radius | 6px | Radio de esquina de la barra de progreso. |
--fe-acc-progress-track | 2px | El riel estático que corre por el borde izquierdo mientras autoplay está activo. |
Autoplay y barra de progreso
Con autoplay activo, el acordeón recorre sus items automáticamente y
muestra una barra de progreso en el item abierto, indicando el tiempo
restante hasta el siguiente avance. La barra es una variable CSS —
--fe-acc-progress va de 0 a 1 y el relleno es
transform: scale(var(--fe-acc-progress)). El script la hace avanzar cada
fotograma (rAF), así que no hay @keyframes (nada que pegar en un
stylesheet) y pausar simplemente detiene el bucle, congelando la barra justo
donde está.
- Solo corre mientras es visible. Un
IntersectionObserverinicia/pausa el ciclo a medida que el acordeón entra/sale del viewport. - Se pausa al interactuar y luego reanuda — ya no se apaga para siempre al
hacer clic. El foco de teclado y abrir un item a mano siempre pausan (la
barra se congela); el hover también pausa salvo que apagues
pauseHover, en cuyo caso sigue corriendo en hover y solo un clic manual pausa. En cualquier caso, al salir reanuda desde el item que dejaste abierto — el tiempo restante se guarda para que el siguiente avance siga en hora. disableOnMobilesalta el autoplay por debajo del breakpoint de tablet (max-width: 767px), re-evaluado en vivo al cruzarlo.- Tematiza la barra por instancia con
progressBar.coloryprogressBar.width— sin tocar el Style Manager. - Respeta
prefers-reduced-motion— el autoplay nunca arranca para visitantes que han pedido movimiento reducido.
Orientación
progressOrientation (en Autoplay options) fija hacia dónde corre la barra:
| Valor | Aspecto |
|---|---|
vertical (por defecto) | Un rail en el borde inline-start del item (rail a toda altura en underline/minimal, barra a ras dentro de la tarjeta en bordered). |
horizontal | Una barra en el borde block-end de cada item, llenándose de izquierda a derecha — limpia en todos los skins. |
El skin numbered corre la barra siempre en horizontal, sin importar esta
opción: un rail izquierdo chocaría con la columna del número.
Las versiones anteriores necesitaban pegar a mano un stylesheet @keyframes
"Fancy Accordion". Eso ya no existe — la barra por variable no necesita nada en
el Style Manager, así que el autoplay funciona en cuanto lo activas.
Móvil
