Acordeón

Cada sección es un <details>. Abrir, cerrar, el soporte de teclado y la búsqueda en la página vienen del navegador, y el acordeón funciona con JavaScript desactivado — algo que importa en unas preguntas frecuentes, que son su uso más común.

Acordeón básico

¿Qué es sitelo?
Un generador de sitios estáticos sobre Vite. Las páginas son funciones que devuelven HTML.
¿Incluye un runtime?
No. Nada llega al navegador salvo que enlaces un script tú mismo.
¿Puedo usar TypeScript?
Sí — .ht.ts y .ht.tsx son extensiones de página como cualquier otra.
accordion({
  items: [
    { title: '¿Qué es sitelo?', content: 'Un generador de sitios estáticos sobre Vite. Las páginas son funciones que devuelven HTML.' },
    { title: '¿Incluye un runtime?', content: 'No. Nada llega al navegador salvo que enlaces un script tú mismo.' },
    { title: '¿Puedo usar TypeScript?', content: 'Sí — .ht.ts y .ht.tsx son extensiones de página como cualquier otra.' },
  ],
})

Abierto por defecto

Abierto al llegar
Esta tiene open: true.
Cerrada
Esta no.
accordion({
  items: [
    { title: 'Abierto al llegar', content: 'Esta tiene open: true.', open: true },
    { title: 'Cerrada', content: 'Esta no.' },
  ],
})

Uno a la vez

Un name compartido hace las secciones mutuamente excluyentes: abrir una cierra las demás. Es el comportamiento propio del navegador para <details name>, no un script.

Primera
Abre otra y esta se cierra.
Segunda
Y esta también.
Tercera
Solo hay una abierta a la vez.
accordion({
  name: 'demo-exclusive',
  items: [
    { title: 'Primera', content: 'Abre otra y esta se cierra.', open: true },
    { title: 'Segunda', content: 'Y esta también.' },
    { title: 'Tercera', content: 'Solo hay una abierta a la vez.' },
  ],
})

Contenido enriquecido

Construye las secciones con accordionItem() cuando el contenido sea más que un párrafo.

Instalar

Añade el paquete y su compañero de marcado:

npm install sitelo javascript-to-html
Configurar

Opcional. Las opciones de Vite van bajo la clave vite.

sitelo.config.js
Desplegar

Publica el directorio de salida en cualquier hosting estático.

NetlifyVercelCloudflare PagesGitHub Pages
accordion(
  accordionItem({ title: 'Instalar', open: true },
    stack({ gap: 'sm' },
      text({ variant: 'small', tone: 'muted' }, 'Añade el paquete y su compañero de marcado:'),
      code('npm install sitelo javascript-to-html'),
    ),
  ),
  accordionItem({ title: 'Configurar' },
    stack({ gap: 'sm' },
      text({ variant: 'small', tone: 'muted' }, 'Opcional. Las opciones de Vite van bajo la clave vite.'),
      code('sitelo.config.js'),
    ),
  ),
  accordionItem({ title: 'Desplegar' },
    stack({ gap: 'sm' },
      text({ variant: 'small', tone: 'muted' }, 'Publica el directorio de salida en cualquier hosting estático.'),
      stack({ direction: 'row', gap: 'sm', wrap: true },
        chip({ size: 'sm' }, 'Netlify'),
        chip({ size: 'sm' }, 'Vercel'),
        chip({ size: 'sm' }, 'Cloudflare Pages'),
        chip({ size: 'sm' }, 'GitHub Pages'),
      ),
    ),
  ),
)

Unas preguntas frecuentes

La forma para la que existe este componente: contenido que ya está en el HTML, plegado para poder ojearlo, y localizable por un buscador porque nunca salió de la página.

¿De verdad es sin configuración?
Un proyecto con un archivo en src/ y sin configuración compila. Todo lo demás es opcional.
¿Cómo funcionan las rutas dinámicas?
Con corchetes en los nombres de archivo. generateStaticParams enumera qué construir.
¿Y la búsqueda?
Pon pagefind: true y la compilación indexa todas las páginas.
return (() => {
  const faq = [
    ['¿De verdad es sin configuración?', 'Un proyecto con un archivo en src/ y sin configuración compila. Todo lo demás es opcional.'],
    ['¿Cómo funcionan las rutas dinámicas?', 'Con corchetes en los nombres de archivo. generateStaticParams enumera qué construir.'],
    ['¿Y la búsqueda?', 'Pon pagefind: true y la compilación indexa todas las páginas.'],
  ]

  return accordion({
    name: 'demo-faq',
    items: faq.map(([title, content]) => ({ title, content })),
  })
})()

Props

accordion():

PropTipoPor defectoDescripción
itemsArray[]Cadenas, u objetos { title, content, open }.
namestring—Un name compartido hace las secciones mutuamente excluyentes.

accordionItem():

PropTipoPor defectoDescripción
titleChild—La línea de resumen.
openbooleanfalseSi empieza desplegada.
namestring—El mismo efecto que en el padre, al construir los ítems a mano.