Accordion Component — Astro

Accessible accordion with collapsible sections, single or multiple open states, and keyboard navigation

Accordion Component

An accessible accordion for collapsible sections. Supports single or multiple open panels and full keyboard navigation.

Props

  • items (array, required) - Array of objects with id, title, and optional content
  • id (string, optional) - Unique identifier for the accordion
  • allowMultiple (boolean, optional) - Allow multiple panels open at once (default: false)
  • defaultExpanded (string | string[], optional) - ID or array of IDs to expand by default (defaults to first item)
  • class (string, optional) - Additional CSS classes

Item Structure

  • id (string, required) - Unique identifier for the item
  • title (string, required) - Heading text for the trigger
  • content (string, optional) - HTML content for the panel (alternative to using slots)

Basic Usage (Single Open)

By default only one panel is open at a time. Provide panel content as children in the same order as the items array:

Live Example

astro astro
---
import Accordion from '../../components/Accordion.astro';
---

<Accordion
  items={[
    { id: 'one', title: 'Section one' },
    { id: 'two', title: 'Section two' },
    { id: 'three', title: 'Section three' },
  ]}
>
  <div><p>Content for section one</p></div>
  <div><p>Content for section two</p></div>
  <div><p>Content for section three</p></div>
</Accordion>

Multiple Panels Open

Set allowMultiple to true to allow multiple panels to be open at once:

Live Example

astro astro
<Accordion
  allowMultiple
  items={[
    { id: 'a', title: 'First' },
    { id: 'b', title: 'Second' },
    { id: 'c', title: 'Third' },
  ]}
>
  <div><p>First panel content</p></div>
  <div><p>Second panel content</p></div>
  <div><p>Third panel content</p></div>
</Accordion>

With Content Property

You can provide panel content directly in the item object:

Live Example

A design system and component library built with semantic CSS variables and Astro.

astro astro
<Accordion
  items={[
    { id: 'faq1', title: 'Question one', content: '<p>Answer one</p>' },
    { id: 'faq2', title: 'Question two', content: '<p>Answer two</p>' },
  ]}
/>

Default Expanded

Control which panel(s) are open initially with defaultExpanded:

Live Example

astro astro
<Accordion
  defaultExpanded="second"
  items={[
    { id: 'first', title: 'First' },
    { id: 'second', title: 'Second' },
    { id: 'third', title: 'Third' },
  ]}
>
  <div><p>First</p></div>
  <div><p>Second</p></div>
  <div><p>Third</p></div>
</Accordion>

Features

  • Collapsible sections - Expand and collapse panels with smooth transitions
  • Single or multiple open - allowMultiple controls whether only one or several panels can be open
  • Keyboard navigation - Arrow Up/Down, Home, End, Enter, and Space
  • ARIA - aria-expanded, aria-controls, region, aria-labelledby
  • Content from props or slots - Use content (HTML string) or pass children for panel content
  • Theme-aware - Uses design system variables

Keyboard Navigation

  • Arrow Down - Focus next trigger
  • Arrow Up - Focus previous trigger
  • Home - Focus first trigger
  • End - Focus last trigger
  • Enter / Space - Toggle focused panel

Svelte & Vanilla: Svelte ¡ Vanilla: same HTML and BEM as in Usage above; add minimal JS for expand/collapse.