Components

Accordion

A React accordion with collapsible Liquid Glass panels and keyboard support.

Accordion renders a stack of disclosure panels on one glass surface. Each entry is a real heading and button, and the panel height animates when it opens.

Basic example

Each entry in items renders a real heading and button. The default plus indicator rotates into a close icon, and the panel animates its height.

Standard shipping takes 3-5 business days. Express delivery arrives in 1-2 business days.

Multiple panels

The default mode keeps a single panel open. Add multiple to let several panels stay expanded at once:

The shared material combines a translucent fill, rim highlight, and backdrop blur.

Override the --ui-* variables to carry the same glass language into light and dark themes.

Sizes

Supports xs / sm / md / lg / xl, defaulting to md. Trigger height, padding, typography, and the indicator scale together.

The trigger height, padding, text, and indicator scale together.
xs

The trigger height, padding, text, and indicator scale together.
sm

The trigger height, padding, text, and indicator scale together.
md

The trigger height, padding, text, and indicator scale together.
lg

The trigger height, padding, text, and indicator scale together.
xl

Controlled usage

value and onValueChange make the open panels fully controlled. The example below can open or collapse every panel from one button:

The shared material combines a translucent fill, rim highlight, and backdrop blur.

Open panels: surface

Disabled

Set disabled on the root to disable every trigger, or on a single item to disable only that panel.

Disabled item

The shared material combines a translucent fill, rim highlight, and backdrop blur.

Disabled accordion

Persistent panels

Closed panels are removed from the DOM by default. Set keepMounted to keep them mounted so form state survives, or hiddenUntilFound to keep them searchable with the browser's find-in-page.

keepMounted

hiddenUntilFound

Accessibility

Each entry renders a native button inside a real heading (an <h3> by default). The trigger exposes aria-expanded; while its panel is open, it also exposes aria-controls. The panel is labelled by its trigger. Enter or Space toggles the focused panel. Disabled triggers stay in the document but are skipped by the Tab key.

Keep the heading text meaningful; the visual style is not a substitute for a real document outline. See the accessibility guide for shared interaction patterns.

API reference

Accordion

PropTypeDefaultDescription
valueValue[]—Controlled expanded item values.
defaultValueValue[][]Initially expanded item values.
onValueChange(value: Value[], details) => void—Called when the expanded values change.
multiplebooleanfalseAllows more than one panel to stay open.
disabledbooleanfalseDisables every trigger.
hiddenUntilFoundbooleanfalseKeeps closed panels searchable with hidden="until-found".
keepMountedbooleanfalseKeeps closed panels mounted in the DOM.
loopFocusboolean—Deprecated. No longer affects keyboard focus.
orientation"horizontal" | "vertical""vertical"Deprecated. No longer affects keyboard focus.
size"xs" | "sm" | "md" | "lg" | "xl""md"Controls trigger height, padding, text, and the indicator.
itemsreadonly AccordionItemProps[]—Panels rendered inside the accordion.
renderReactElement | ((props, state) => ReactElement)—Replaces the root element.
refRef<HTMLDivElement>—Ref forwarded to the root element.
classNamestring—Tailwind classes merged into the root.
styleCSSProperties—Inline styles merged into the same element as className.
ui{ root?: ClassValue; glass?: ClassValue; overlay?: ClassValue; content?: ClassValue; item?: ClassValue; header?: ClassValue; trigger?: ClassValue; title?: ClassValue; indicator?: ClassValue; indicatorIcon?: ClassValue; panel?: ClassValue; panelContent?: ClassValue }—Tailwind classes for internal slots, keyed by data-slot.

AccordionItemProps

PropTypeDefaultDescription
valueany—Required identifier used by the accordion value.
titleReactNode—Required visible heading inside the trigger.
contentReactNode—Panel content.
indicatorReactNode | falseBuilt-in plus iconReplaces the default indicator. Set to false to hide it.
disabledbooleanfalseDisables this item.
onOpenChange(open: boolean, details) => void—Called when this panel opens or closes.
renderReactElement | ((props, state) => ReactElement)—Replaces the item root element.
refRef<HTMLDivElement>—Ref forwarded to the item root.
classNamestring—Tailwind classes merged into the item root.
styleCSSProperties—Inline styles merged into the same element as className.
ui{ item?: ClassValue; header?: ClassValue; trigger?: ClassValue; title?: ClassValue; indicator?: ClassValue; indicatorIcon?: ClassValue; panel?: ClassValue; panelContent?: ClassValue }—Tailwind classes for this item's internal slots, keyed by data-slot.

Root ui is merged into every item first, then the item's ui, then the item's className.

AttributeDescription
data-disabledPresent when the accordion or an item is disabled.
data-orientationIndicates the orientation (horizontal or vertical).
data-indexIndicates the item index on item and trigger elements.
data-openPresent when an item is open.
data-panel-openPresent on a trigger while its panel is open.
data-starting-stylePresent when a panel begins animating in.
data-ending-stylePresent when a panel is animating out.
data-slotMarks internal parts (root, glass, overlay, content, item, header, trigger, title, indicator, indicator-icon, panel, panel-content).

Theming

The component uses the shared glass material. Tune shared --ui-glass-* tokens on a parent, use className for layout, and use ui for internal slots keyed by data-slot. Component-specific values live in src/theme/accordion.ts. See the theming guide for token layers and presets.

  • Tabs — For switching between sibling views instead of stacking disclosures.
  • Toggle — For a single on/off action without a panel.
  • Scroll Area — When an expanded panel needs its own scroll container.