Browse the docs
Accordion
Collapsible sections that keep the native <details>/<summary> markup —
keyboard support and semantics come from the platform — while the accordion
primitive manages the open state in React, so exclusive groups work in
every browser and the state is observable via onToggle.
This component needs the accordion primitive — two ways to get it:
- Copy: fetch
/r/primitives/accordion.txt— one file with the shared core embedded — and save it asprimitives/accordion.js. - Install:
npm install @presetui/ui— the primitives are bundled, no second package — then use the Source · npm tab below, whose import already points at@presetui/ui/primitives/accordion.
When am I billed?
What counts as a seat?
Can I cancel any time?
Props
| Prop | Values | Default | Description |
|---|---|---|---|
items | array | required | One object per section: { value, label, content }. |
name | string | — | Set it to make the group exclusive. |
defaultOpen | string | — | value of the section that starts open. |
className | string | "" | Appended after the component's own classes. |
Common patterns
// Any number open at once
<Accordion items={faqs} />
// Exclusive — opening one closes the others
<Accordion name="faq" items={faqs} defaultOpen="billing" />Notes
Passing name makes the group exclusive — opening one section closes the
others. Exclusivity is handled by the primitive in JavaScript, so unlike the
native name attribute on <details> it doesn't need Chrome 120+ / Safari
17.2+ / Firefox 130+.
For controlled open state, custom trigger markup, or nesting, compose the
primitive directly: AccordionRoot, AccordionItem, AccordionTrigger,
AccordionContent — type="single" | "multiple", value/onValueChange.
Content in a closed <details> is in the DOM but not rendered, so in-page
search won't find it in most browsers. Don't hide anything essential in there.