Skip to content

Accordion ​

A vertically stacked set of collapsible sections that allows users to expand and collapse content panels.

Features ​

  • ✅ Smooth collapse/expand animations
  • ✅ Accessible ARIA attributes and roles
  • ✅ Full keyboard navigation (Arrow keys, Home, End)
  • ✅ Single or multiple items expanded

Installation ​

js
import Alpine from 'alpinejs'
import accordion from 'alpine-headless-ui/accordion'

Alpine.plugin(accordion)
Alpine.start()

Examples ​

Basic Accordion ​

Alpine Headless UI provides unstyled, accessible UI primitives for Alpine.js applications.

It provides behavior and accessibility while you control the styling and markup structure.

Yes, it's open source and free to use under the MIT license.

With Icon Indicator ​

Absolutely! The components are completely unstyled, so you have full control over the appearance.

Yes, it works perfectly with Tailwind CSS, plain CSS, or any styling solution.

Multiple Items Open ​

This accordion allows multiple items to be open at the same time.

Both sections can be expanded simultaneously.

Try expanding all three!

Non-Collapsible ​

When collapsible is false, at least one item must always be open.

You can't collapse all items when collapsible is false.

API Reference ​

Component Props ​

PropTypeDefaultDescription
valuestring[][]Array of open item IDs
multiplebooleanfalseAllow multiple items to be open
collapsiblebooleantrueAllow all items to be closed
disabledbooleanfalseDisable all accordion items

Parts ​

PartDescription
x-accordion:item="id"Accordion item container with unique ID
x-accordion:item-headerHeading wrapper around the trigger (sets role="heading")
x-accordion:item-triggerButton that toggles the item
x-accordion:item-contentContent that is shown/hidden
x-accordion:item-indicatorOptional visual indicator element

Data Attributes ​

AttributeDescription
data-scopeAlways set to accordion
data-partIdentifies the part (root, item, item-header, item-trigger, item-content, item-indicator)
data-stateCurrent state (open or closed)
data-disabledPresent when disabled

Events ​

EventDetailDescription
change{ value: string[] }Fired when the open items change
focus-change{ value: string | null }Fired when the focused item changes

Keyboard Interactions ​

KeyAction
ArrowDownMove focus to next item trigger
ArrowUpMove focus to previous item trigger
HomeMove focus to first item trigger
EndMove focus to last item trigger

Accessing State ​

You can access the accordion API using $accordion:

html
<div x-accordion>
  <div x-data>
    <p x-text="'Open items: ' + $accordion.value.length"></p>
  </div>

  <div x-accordion:item="'item-1'">
    <!-- Item content -->
  </div>
</div>

Available properties:

  • value - Array of open item IDs
  • multiple - Whether multiple items can be open
  • collapsible - Whether all items can be closed
  • disabled - Whether accordion is disabled
  • focusedValue - ID of currently focused item
  • isOpen(id) - Check if item is open
  • toggle(id) - Toggle an item
  • setValue(value) - Set open items programmatically

Accessibility ​

ARIA Attributes ​

The accordion automatically includes:

  • type="button" on triggers
  • aria-expanded on triggers (true/false)
  • aria-controls on triggers pointing to the content panel id
  • role="region" on content panels
  • aria-labelledby on content panels pointing to the trigger id
  • role="heading" on x-accordion:item-header
  • Proper data attributes for state

Heading Level ​

The WAI-ARIA accordion pattern requires each trigger to be inside a heading element. Wrap each trigger with x-accordion:item-header on a native heading (<h2>, <h3>, etc.) at the level appropriate for your page's document outline. If you use a non-heading element, provide an explicit aria-level:

html
<div x-accordion:item-header aria-level="3">
  <button x-accordion:item-trigger>...</button>
</div>

Keyboard Support ​

KeyAction
Space / EnterToggle focused accordion item
ArrowDownMove focus to next trigger
ArrowUpMove focus to previous trigger
HomeMove focus to first trigger
EndMove focus to last trigger

See Also ​

  • Collapsible - Single collapsible section
  • Tabs - Alternative pattern for showing/hiding content

Built with Alpine.js and inspired by Zag.js