Usage#
import { useAccordion, useAccordionPanel } from '@primereact/headless/accordion';const accordion = useAccordion({ defaultValue: '1' });
const { rootProps } = accordion;
const { panelProps, headerProps, triggerProps, contentProps, indicatorProps, state } = useAccordionPanel({
value: '1',
context: accordion
});
<div {...rootProps}>
<div {...panelProps}>
<div {...headerProps}>
<button {...triggerProps}>
<span {...indicatorProps} />
</button>
</div>
{state.open && <div {...contentProps}></div>}
</div>
</div>;useAccordion manages root state while useAccordionPanel consumes that context to return prop objects for each panel element — see Primitive for a component-based API.
Features#
- Two-hook architecture —
useAccordionowns root state and keyboard focus cycling;useAccordionPanelconsumes its context to render individual panels - Single or multiple expansion — one open panel at a time or an array of open keys, switchable via the
multipleflag - Controlled or uncontrolled — drive the active key(s) from outside or let the hook manage its own state
- Focus-triggered expansion — opt into
openOnFocusto open a panel the moment its trigger is focused via keyboard - Imperative controls —
updateValue()toggles a key andisItemActive()checks open state from custom code paths - Full render control —
state.openlets you conditionally mount content, pair with CSS, or wire up animation hooks
Working with callbacks#
Controlled active panel#
Drive the open panel from outside state by pairing value with onValueChange.
const [value, setValue] = React.useState<string | null>('1');
const accordion = useAccordion({
value,
onValueChange: (e) => setValue(e.value)
});onValueChange receives { originalEvent, value } — value is a single key in single mode or the new array in multiple mode.
Multiple open panels#
Set multiple to keep several panels open at once. Both value and defaultValue become arrays.
const accordion = useAccordion({
multiple: true,
defaultValue: ['1', '2'],
onValueChange: (e) => console.log(e.value) // string[]
});Imperative toggling from custom UI#
Use updateValue to toggle panels from buttons that live outside the accordion tree, such as a sidebar or toolbar.
const accordion = useAccordion({ multiple: true });
<button onClick={(e) => accordion.updateValue(e, '3')}>Toggle section 3</button>;
if (accordion.isItemActive('2')) {
// run logic only when panel 2 is open
}In single mode updateValue toggles between the key and null; in multiple mode it adds or removes the key from the array.
Animated enter/leave with state.open#
Because the hook leaves content rendering to you, pair state.open with a motion primitive to animate transitions.
const { contentProps, state } = useAccordionPanel({ value: '1', context: accordion });
<AnimatePresence>
{state.open && (
<motion.div {...contentProps} initial={{ height: 0 }} animate={{ height: 'auto' }} exit={{ height: 0 }}>
Panel content
</motion.div>
)}
</AnimatePresence>;For a built-in approach, use the useMotion hook alongside state.open.
Styling with data attributes#
Every prop object includes data-scope="accordion" and a data-part attribute. State-dependent attributes are applied automatically so styling can stay in CSS.
| Scope | Part | States |
|---|---|---|
accordion | panel | data-open, data-closed, data-disabled |
accordion | trigger | data-content-open, data-content-closed |
accordion | content | data-open, data-closed |
[data-scope='accordion'][data-part='trigger'] {
font-weight: 600;
}
[data-scope='accordion'][data-part='content'][data-open] {
animation: slideDown 200ms ease-out;
}
[data-scope='accordion'][data-part='content'][data-closed] {
animation: slideUp 200ms ease-out;
}
[data-scope='accordion'][data-part='panel'][data-disabled] {
opacity: 0.5;
}
[data-scope='accordion'][data-part='trigger'][data-content-open] {
color: blue;
font-weight: 700;
}API#
useAccordion#
| Name | Type | Default |
|---|---|---|
defaultValue | string | number | (string | number)[] | — |
| Default value of the active panel or an array of values in multiple mode. | ||
value | string | number | (string | number)[] | — |
| Value of the active panel or an array of values in multiple mode. | ||
multiple | boolean | false |
| When enabled, multiple tabs can be activated at the same time. | ||
disabled | boolean | false |
| When disabled, the component cannot be interacted with. | ||
tabIndex | number | 0 |
| Index of the element in tabbing order. | ||
openOnFocus | boolean | false |
| When enabled, the accordion panel will be opened on focus. | ||
onValueChange | (event: useAccordionChangeEvent) => void | — |
| Callback fired when the accordion's value changes. | ||
useAccordionPanel#
| Name | Type | Default |
|---|---|---|
value | string | number | — |
| Unique value of the panel. | ||
disabled | boolean | false |
| Whether the panel is disabled. | ||
context | useAccordionInstance | — |
| The parent accordion instance providing state and methods. | ||
Accessibility#
Arrow keys move between headers, Home/End jump to first/last, and Enter or Space toggles the focused panel. See Primitive for full WAI-ARIA compliance details.