Accordion
The <x-wirekit::accordion> component creates collapsible content sections with single or multiple open modes. It follows the WAI-ARIA Accordion pattern.
Accordion vs Collapsible vs FAQ — when to use which
- Accordion (this component) — a coordinated group of panels with optional single-open behavior and card chrome. Opening one panel can close the others.
- Collapsible — a single independent show/hide (a "read more", an advanced-options panel), or a stack of them with no coordination.
- FAQ — this accordion, specialized for questions, that also emits FAQPage structured data derived from what it renders. Use it for a real question list instead of hand-building one here.
Usage
Width & Layout
The accordion fills its parent width. Control the width with Tailwind classes directly on the component:
<x-wirekit::accordion class="max-w-lg">
…
</x-wirekit::accordion>
Modes
Single mode
Opening one item closes all others — similar to radio buttons.
Multiple mode
Any combination of items can be open — similar to checkboxes.
With Icons
Use the header named slot to render custom header content with icons:
Variants
The variant prop changes the container chrome. bordered (default) is a
self-contained card; flush drops the outline so the accordion sits inline in
page content (ideal for an FAQ block); separated turns each item into its own
standalone card with a gap between them.
Size
size="lg" gives the trigger roomier padding and a larger title — useful for
marketing pages and touch-first layouts.
Long Titles
When the accordion has a fixed width, long titles wrap naturally while the chevron stays aligned:
Props
<x-wirekit::accordion>
| Prop | Type | Default | Description |
|---|---|---|---|
mode |
string |
'single' |
'single' (only one open at a time) or 'multiple' |
variant |
string |
'bordered' |
'bordered' (card with outline), 'flush' (inline, dividers only), or 'separated' (each item its own card) |
size |
string |
'md' |
Row density — 'md' or 'lg' (roomier padding + larger trigger text) |
scope |
string|null |
null |
Scoped personalization key |
<x-wirekit::accordion.item>
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string|null |
auto-generated | Stable identifier used for Alpine state and ARIA wiring |
title |
string |
'' |
Header text (or use the header named slot) |
scope |
string|null |
null |
Scoped personalization key |
Accessibility
- Each header is an
<h3>containing a<button>(allows AT heading navigation) - Button:
aria-expanded(dynamic),aria-controls(linked to panel) - Panel:
role="region",aria-labelledby(linked to button) - Chevron rotates 180° when open — decorative,
aria-hidden="true"
Keyboard Interaction
| Key | Action |
|---|---|
Tab |
Move focus to the next accordion header |
Shift+Tab |
Move focus to the previous accordion header |
Enter / Space |
Toggle the focused panel |
ArrowDown / ArrowUp |
Move between accordion headers |
Home / End |
Move to the first / last header |
Pitfalls
- Don't nest accordions more than two levels deep. WAI-ARIA Authoring Practices warn that screen-reader users lose track of the hierarchy. Reach for
<x-wirekit::tree-view>for genuinely nested data. - Don't auto-expand all panels on load. Defeats the disclosure pattern — if everything is open, the accordion is just a stack of headings. Open at most one initial panel.
Design Tokens
| Token | Used for |
|---|---|
--color-wk-bg-elevated |
Accordion container background |
--color-wk-border |
Outer border + per-item separator |
--border-wk-width |
Border width |
--radius-wk-lg |
Container border radius |
Config Defaults
The defaults live in config/wirekit.php under components.accordion. Override them globally:
'components' => [
'accordion' => ['mode' => 'multiple'], // allow multiple items open by default
],
Further Reading
- WAI-ARIA Accordion Pattern — the authoring pattern this component implements
- MDN:
aria-expanded - MDN:
role="region" - HTML
<details>vs ARIA Accordion — when to choose each