Accordion

Stacked sections that expand and collapse; one open at a time unless multiple. Panel height animates via CSS.

WAI-ARIA pattern

Installation

npx nuecrea-ui add accordion

Usage

import * as Accordion from '@/components/ui/accordion';

const items = [
  {
    value: 'shipping',
    title: 'How long does shipping take?',
    body: 'Orders ship within 2 business days.',
  },
  { value: 'returns', title: 'Can I return an item?', body: 'Yes, within 30 days of delivery.' },
  { value: 'gift', title: 'Do you offer gift wrapping?', body: 'Not yet.', disabled: true },
  { value: 'support', title: 'How do I contact support?', body: 'Email help@example.com.' },
];

export default function AccordionStory() {
  return (
    <main className="grid max-w-md gap-8">
      <Accordion.Root defaultValue={['shipping']}>
        {items.map((item) => (
          <Accordion.Item
            key={item.value}
            value={item.value}
            disabled={item.disabled}
          >
            <Accordion.Header>
              <Accordion.Trigger>{item.title}</Accordion.Trigger>
            </Accordion.Header>
            <Accordion.Panel>{item.body}</Accordion.Panel>
          </Accordion.Item>
        ))}
      </Accordion.Root>

      <Accordion.Root multiple disabled defaultValue={['locked']}>
        <Accordion.Item value="locked">
          <Accordion.Header>
            <Accordion.Trigger>Locked section</Accordion.Trigger>
          </Accordion.Header>
          <Accordion.Panel>Hidden content.</Accordion.Panel>
        </Accordion.Item>
      </Accordion.Root>
    </main>
  );
}

API reference

Accordion.Root

Groups items; owns which are open. Renders <div>.

PropTypeDefaultDescription
valueunknown[]—Controlled open item values.
defaultValueunknown[]—Initially open item values.
multiplebooleanfalseAllow several open items.
disabledbooleanfalseDisable every item.
keepMountedbooleanfalseKeep closed panels in the DOM (hidden).
EventPayloadDescription
onValueChangeunknown[]Fired when items open or close. Angular: the `value` model's change event.
Data attributePresent when
data-orientationalways: vertical
data-disabledthe accordion is disabled

Accordion.Item

One section. Renders <div>.

PropTypeDefaultDescription
valueunknown—Identifies the item. Generated when unset.
disabledbooleanfalseCannot be toggled.
EventPayloadDescription
onOpenChangebooleanFired when this item opens or closes.
Data attributePresent when
data-orientationalways: vertical
data-openthe item is open
data-closedthe item is closed
data-hiddenthe item's panel is hidden
data-disabledthe item (or whole accordion) is disabled
data-indexalways: the item's index

Accordion.Trigger

Toggles the panel. A plain button in the tab order; the styled version appends a chevron. Renders <button>.

Data attributePresent when
data-orientationalways: vertical
data-panel-openthe panel is open
data-hiddenthe item's panel is hidden
data-disabledthe item (or whole accordion) is disabled
data-indexalways: the item's index

Accordion.Panel

The section content (role=region). Hidden when closed (unmounted in React). Renders <div> with role region.

PropTypeDefaultDescription
keepMountedbooleanfalseKeep in the DOM while closed.
Data attributePresent when
data-orientationalways: vertical
data-openthe item is open
data-closedanimating closed
data-disabledthe item (or whole accordion) is disabled
data-indexalways: the item's index
data-starting-styleanimating open
data-ending-styleanimating closed
CSS variableDescription
--accordion-panel-heightContent height in px while animating, auto when open.
--accordion-panel-widthContent width in px while animating, auto when open.

Keyboard

KeyAction
Enter / SpaceToggle the focused item's panel.
TabMove between triggers (no arrow-key navigation, as in Base UI).