---
title: Accordion
description: Collapsible content panels
related:
  - /components/collapsible
  - /components/faq
  - /components/reveal
visibility: guest
draft: false
---

# Accordion

The `<x-wirekit::accordion>` component creates collapsible content sections with single or multiple open modes. It follows the [WAI-ARIA Accordion pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/).

::: info 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](/components/collapsible)** — a *single* independent show/hide (a "read more", an advanced-options panel), or a stack of them with no coordination.
- **[FAQ](/components/faq)** — this accordion, specialized for questions, that also emits [FAQPage](/components/structured-data) structured data derived from what it renders. Use it for a real question list instead of hand-building one here.
:::

## Usage

:::preview{title="Single-Open Accordion"}
<x-wirekit::accordion>
    <x-wirekit::accordion.item title="What is WireKit?" id="faq-1">
        WireKit is a free, MIT-licensed UI component library for Laravel Livewire built on Tailwind CSS v4.
    </x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Is it free?" id="faq-2">
        Yes, WireKit is completely free and open source under the MIT license.
    </x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Does it support dark mode?" id="faq-3">
        Absolutely — all components auto-switch via the `.dark` class on any ancestor.
    </x-wirekit::accordion.item>
</x-wirekit::accordion>
:::

## Width & Layout

The accordion fills its parent width. Control the width with Tailwind classes directly on the component:

```blade
<x-wirekit::accordion class="max-w-lg">
    …
</x-wirekit::accordion>
```

## Modes

### Single mode

Opening one item closes all others — similar to radio buttons.

:::preview{title="Single-Mode Accordion"}
<x-wirekit::accordion>
    <x-wirekit::accordion.item title="Section A" id="s-1">Content A.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Section B" id="s-2">Content B.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Section C" id="s-3">Content C.</x-wirekit::accordion.item>
</x-wirekit::accordion>
:::

### Multiple mode

Any combination of items can be open — similar to checkboxes.

:::preview{title="Multiple-Open Accordion"}
<x-wirekit::accordion mode="multiple">
    <x-wirekit::accordion.item title="Section A" id="m-1">Content A.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Section B" id="m-2">Content B.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Section C" id="m-3">Content C.</x-wirekit::accordion.item>
</x-wirekit::accordion>
:::

## With Icons

Use the `header` named slot to render custom header content with icons:

:::preview{title="Accordion with Icons"}
<x-wirekit::accordion>
    <x-wirekit::accordion.item id="icon-1">
        <x-slot:header>
            <x-wirekit::row gap="sm">
                <x-wirekit::icon name="user" />
                Account Settings
            </x-wirekit::row>
        </x-slot:header>
        Manage your account details, email preferences, and security settings.
    </x-wirekit::accordion.item>
    <x-wirekit::accordion.item id="icon-2">
        <x-slot:header>
            <x-wirekit::row gap="sm">
                <x-wirekit::icon name="edit" />
                Notifications
            </x-wirekit::row>
        </x-slot:header>
        Choose which notifications you want to receive and how.
    </x-wirekit::accordion.item>
    <x-wirekit::accordion.item id="icon-3">
        <x-slot:header>
            <x-wirekit::row gap="sm">
                <x-wirekit::icon name="calendar" />
                Billing
            </x-wirekit::row>
        </x-slot:header>
        View invoices, update payment methods, and manage your subscription.
    </x-wirekit::accordion.item>
</x-wirekit::accordion>
:::

## 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.

:::preview{title="Flush variant"}
<x-wirekit::accordion variant="flush">
    <x-wirekit::accordion.item title="Do I need a credit card to start?" id="f-1">No — the free tier needs no payment details.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Can I change plans later?" id="f-2">Yes, upgrade or downgrade at any time from billing.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Where is my data stored?" id="f-3">In your selected region, encrypted at rest.</x-wirekit::accordion.item>
</x-wirekit::accordion>
:::

:::preview{title="Separated variant"}
<x-wirekit::accordion variant="separated">
    <x-wirekit::accordion.item title="Shipping" id="sep-1">Free standard shipping on orders over $50.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Returns" id="sep-2">30-day returns on unworn items with the original tags.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Warranty" id="sep-3">Two-year limited warranty against manufacturing defects.</x-wirekit::accordion.item>
</x-wirekit::accordion>
:::

## Size

`size="lg"` gives the trigger roomier padding and a larger title — useful for
marketing pages and touch-first layouts.

:::preview{title="Roomy (lg) accordion"}
<x-wirekit::accordion size="lg" variant="separated">
    <x-wirekit::accordion.item title="What makes WireKit different?" id="lg-1">Every component is theme-token-driven and ships with full keyboard and screen-reader support out of the box.</x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Does it work with my existing Tailwind setup?" id="lg-2">Yes — WireKit layers on top of Tailwind v4 with a CSS-first token system.</x-wirekit::accordion.item>
</x-wirekit::accordion>
:::

## Long Titles

When the accordion has a fixed width, long titles wrap naturally while the chevron stays aligned:

:::preview{title="Accordion with Long Titles"}
<x-wirekit::accordion style="max-width: 24rem;">
    <x-wirekit::accordion.item title="What happens when the title text is very long and wraps to multiple lines?" id="long-1">
        The title wraps naturally within the available space. The chevron stays right-aligned and vertically centered.
    </x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Short title" id="long-2">
        This one is short for comparison.
    </x-wirekit::accordion.item>
    <x-wirekit::accordion.item title="Another longer title that demonstrates how the component handles multi-line header text gracefully" id="long-3">
        The gap between the text and the chevron ensures they never collide, even with long content.
    </x-wirekit::accordion.item>
</x-wirekit::accordion>
:::

## 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:

```php
'components' => [
    'accordion' => ['mode' => 'multiple'], // allow multiple items open by default
],
```

## Further Reading

- [WAI-ARIA Accordion Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) — the authoring pattern this component implements
- [MDN: `aria-expanded`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded)
- [MDN: `role="region"`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/region_role)
- [HTML `<details>` vs ARIA Accordion](https://www.scottohara.me/blog/2022/09/12/details-summary.html) — when to choose each
