Accordion
StableStacked sections that expand in place. Lets users scan headings and open only what they need.
When to use
Use it for
- Long reference content where users look for one section: token groups, FAQ, advanced settings.
- multiple when users compare sections; single (default) when sections are alternatives.
- flush inside a card or a side panel, contained on a page.
Not for
- Content everyone needs: do not hide it behind a click.
- Switching between views of the same data: use Tabs.
- Steps in a sequence: use a stepped layout with headings.
Do and don't
Every example is rendered with the real component, so it always matches what ships.
Headings that work as a table of contents
Users scan the closed state. Name each section by its content, and show a count in meta when it helps.
Nesting accordions
A collapsible inside a collapsible hides content twice. Flatten the structure or split the page.
Accessibility
- Base UI Accordion: each trigger is a button inside a heading (headingLevel, default h3) with aria-expanded and aria-controls.
- Panels are regions labelled by their trigger. Enter and Space toggle; Tab moves between triggers.
- Disabled items stay visible but cannot open.
- The height animation uses motion tokens and collapses to 0ms with reduced motion.
Anatomy and tokens
Read from packages/react/src/components/Accordion/Accordion.module.css at build time. Every value is a token: open one to see its
alias chain in both themes.
- Container
.accordion - Contained appearance
.contained - Item
.item + .item - Trigger button
.trigger - Contained appearance, hover
@media (hover: hover) .contained .trigger:not([data-disabled]):hover - Flush appearance, hover
@media (hover: hover) .flush .trigger:not([data-disabled]):hover .title - Trigger button, focus
.trigger:focus-visible - Trigger button
.trigger[data-disabled] - Meta
.meta - Chevron
.chevron - Panel
.panel - Panel content
.content
Props
Parsed from the TypeScript types in packages/react/src/components/Accordion/Accordion.tsx, so this table cannot drift from the
code.
| Prop | Type | Default | Description |
|---|---|---|---|
children required | ReactNode | none | No description in the code yet. |
multiple | boolean | false | Allow several panels open at once. Default `false`. |
defaultValue | string[] | none | Values of the items open by default (uncontrolled). |
value | string[] | none | Values of the open items (controlled). |
onValueChange | (value: string[]) => void | none | No description in the code yet. |
headingLevel | 2 | 3 | 4 | 5 | 6 | 3 | Heading level of every item trigger, to fit the page outline. Default `3`. |
appearance | 'contained' | 'flush' | 'contained' | `contained` draws an outer border (inside a page); `flush` only separates items (inside a card). Default `contained`. |
disabled | boolean | none | No description in the code yet. |
className | string | none | No description in the code yet. |
Playground
Change the props and see the real Accordion update. Controls are generated from the TypeScript props; nothing here changes the system.
<Accordion />Workbench
For contributors: every state with the accessibility panel, in the component workbench (Storybook). The stories double as visual test fixtures; the guidance on this page is the user documentation (open Accordion in Storybook) .
Embed Storybook stories here (4)
Loads from https://bridge-storybook.floriangouloubi.com (set STORYBOOK_URL at build time). If Storybook is not running, the frames stay
empty.
Default
Multiple
Flush
AllStates
Changelog
- New
Data display: Card restyled as a flat plate with an `interactive` option and padding sizes; Badge gains `appearance` (subtle, now the default, or solid), a dot, icons and sizes (existing solid badges must pass `appearance="solid"` to keep their look); new Avatar and AvatarGroup, Table (sortable headers with aria-sort, selectable rows, sticky header, focusable scroll region, useTableSort), Accordion, Tag (removable, toggleable), Divider and Kbd. Adds avatar, tag, kbd, divider and accordion component tokens.
Unreleased (current version 0.1.0, no release tagged yet) , Oct 17, 2026