Accordion
Stacked headings that each reveal a panel, with height motion you can reverse mid-way and panels that stay searchable while closed.
pnpm dlx shadcn@latest add https://hextaui.com/r/accordion.jsonAdds the component, the HextaUI theme tokens and any HextaUI components it depends on.
Add the theme tokens to your global CSS, if you haven’t yet.
Install the dependencies.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnCopy and paste the following code into your project.
components/ui/accordion.tsx Update the import paths to match your project setup.
Outline
Items share one bordered surface, with the outer corners rounded.
Separated
Each item is its own card.
Ghost
No borders. Triggers get a soft fill on hover and when open.
Multiple
Set multiple to let more than one item stay open.
Disabled
Disable a single item with disabled on <AccordionItem />, or the whole accordion on the root.
Controlled
Pass value and onValueChange to keep the open items in your own state.
Custom icon
Pass any element to icon. Style its open state with group-data-panel-open/accordion-trigger.
Leading icons
Icons before the label are sized and aligned for you. icon={null} removes the chevron.
Long content
Long titles wrap while the icon stays on the first line. Closed panels stay searchable, so Cmd/Ctrl+F for “retention” opens this one.
Your workspace is kept for 30 days after cancellation. During that time you can reactivate and everything is restored exactly as you left it.
After the retention window, data is permanently deleted. Read the data policy for details.
Nested
An inner accordion keeps its own variant, focus styles and arrow-key navigation.
Right to left
Content, icons and the open motion follow the reading direction.
| Key | Action |
|---|---|
| EnterSpace | Opens or closes the focused item. |
| ↓ | Moves focus to the next trigger. |
| ↑ | Moves focus to the previous trigger. |
| Home | Moves focus to the first trigger. |
| End | Moves focus to the last trigger. |
| Tab | Moves focus into the open panel, then on to the next trigger. |
Built on the Base UI accordion. Every part accepts the props of the primitive it wraps.
| Prop | Type | Default |
|---|---|---|
variant | "default" | "outline" | "separated" | "ghost" | "default" |
multipleAllow more than one item to be open. | boolean | false |
value | Value[] | – |
defaultValue | Value[] | – |
onValueChange | (value: Value[], details) => void | – |
disabled | boolean | false |
hiddenUntilFoundKeep closed panels findable with the browser’s page search. | boolean | true |
keepMountedIgnored while hiddenUntilFound is on. | boolean | false |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="accordion" | Target the root in CSS. |
data-variant | The current variant. |
data-disabled | Present when the accordion is disabled. |
| Prop | Type | Default |
|---|---|---|
valueGenerated automatically when omitted. | Value | – |
disabled | boolean | false |
onOpenChange | (open: boolean, details) => void | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="accordion-item" | Target items in CSS. |
data-open | Present when the item is open. |
data-disabled | Present when the item is disabled. |
data-index | The item’s position, starting at 0. |
| Prop | Type | Default |
|---|---|---|
iconnull removes the icon. | ReactNode | null | <IconChevronDown /> |
render | ReactElement | (props, state) => ReactElement | <button> |
| Attribute | Description |
|---|---|
data-slot="accordion-trigger" | Target triggers in CSS. |
data-panel-open | Present when its panel is open. Style the icon with group-data-panel-open/accordion-trigger. |
data-disabled | Present when the item is disabled. |
| Prop | Type | Default |
|---|---|---|
classNameApplied to the inner wrapper, so padding never fights the height animation. | string | – |
keepMounted | boolean | false |
hiddenUntilFound | boolean | – |
| Attribute | Description |
|---|---|
data-slot="accordion-content" | Target panels in CSS. |
data-open | Present when the panel is open. |
data-starting-style | Present while the panel animates in. |
data-ending-style | Present while the panel animates out. |
data-settled | Present once the panel is fully open. It stops clipping then, so focus rings inside a nested accordion show in full. |
--accordion-panel-height | The panel’s measured height, used for the height animation. |