react-accessible-accordion, react-collapse, and react-collapsible are React libraries designed to create collapsible UI components such as accordions, expandable panels, and toggleable sections. These packages help developers show or hide content based on user interaction while managing animation, state, and — in some cases — accessibility concerns. Each library takes a different approach: react-accessible-accordion emphasizes WAI-ARIA compliance and built-in keyboard navigation; react-collapse offers a minimal, unopinionated collapse primitive focused on smooth animation; and react-collapsible provides a simple, self-contained toggle component with basic styling and animation but limited accessibility support.
When you need to show and hide content in a UI — like FAQs, settings panels, or product details — collapsible components are essential. But not all implementations handle accessibility, performance, or developer experience equally. Let’s compare three popular React packages for this task: react-accessible-accordion, react-collapse, and react-collapsible.
react-accessible-accordion is built from the ground up with WAI-ARIA standards in mind. It automatically manages ARIA attributes (aria-expanded, aria-controls, etc.), keyboard navigation (arrow keys, Home/End), and focus management. If your team prioritizes inclusive design and compliance (e.g., WCAG), this is the only one of the three that enforces accessibility by default.
// react-accessible-accordion
import {
Accordion,
AccordionItem,
AccordionItemHeading,
AccordionItemButton,
AccordionItemPanel
} from 'react-accessible-accordion';
<Accordion>
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton>FAQ #1</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>
<p>Answer goes here.</p>
</AccordionItemPanel>
</AccordionItem>
</Accordion>
react-collapse takes a minimalist, unopinionated approach. It provides a single <Collapse> component that animates height transitions using CSS transforms and requestAnimationFrame. It doesn’t include any accordion logic — you must manage open/closed state yourself. This gives you full control but shifts the burden of accessibility and interaction patterns to you.
// react-collapse
import Collapse from 'react-collapse';
function MyCollapsible({ isOpen }) {
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
<Collapse isOpened={isOpen}>
<div>Content here</div>
</Collapse>
</div>
);
}
react-collapsible offers a simple, self-contained toggle component with basic animation. It bundles the trigger button and panel together, reducing boilerplate compared to react-collapse. However, it lacks built-in ARIA support and requires manual implementation of keyboard navigation and screen reader announcements.
// react-collapsible
import Collapsible from 'react-collapsible';
<Collapsible trigger="Click me">
<p>Hidden content</p>
</Collapsible>
Only react-accessible-accordion ships with full WAI-ARIA compliance:
aria-controlsaria-expanded toggled automaticallyIn contrast, react-collapse and react-collapsible provide zero accessibility features. You must manually:
role="button" or use real <button> elementsaria-expanded, aria-controls, and id associationsExample of what you’d need to add manually with react-collapsible:
// Manual ARIA with react-collapsible (not built-in)
const [isOpen, setIsOpen] = useState(false);
const panelId = 'panel-' + Math.random().toString(36).substr(2, 9);
<>
<button
aria-expanded={isOpen}
aria-controls={panelId}
onClick={() => setIsOpen(!isOpen)}
>
Toggle
</button>
{isOpen && (
<div id={panelId} role="region">
<p>Content</p>
</div>
)}
</>
This extra work is error-prone and often neglected in practice — making react-accessible-accordion the safer choice for production apps where accessibility is non-negotiable.
All three libraries animate height changes, but they do it differently:
react-accessible-accordion: Uses CSS transitions on max-height. Smooth but can be less performant with very tall content since max-height must be set to an estimated maximum.
react-collapse: Measures content height dynamically and uses transform: scaleY() combined with height for smoother, GPU-accelerated animations. More complex internally but better for variable or dynamic content.
react-collapsible: Relies on CSS max-height transitions similar to the first option. Simpler but shares the same limitation with unknown content heights.
If you’re animating large or dynamic content (e.g., user-generated text), react-collapse’s measurement-based approach avoids layout thrashing and feels more responsive.
react-accessible-accordion includes internal state management. You can let it handle which panels are open, or override behavior via props like preExpanded and onChange. It supports both single and multi-open modes out of the box.
react-collapse is completely stateless. You pass isOpened={true/false} and handle all logic yourself. This integrates cleanly with Redux, Zustand, or any state system but adds wiring overhead.
react-collapsible manages its own open/closed state internally but allows limited control via open and onOpen/onClose props. However, it doesn’t support controlled mode as robustly as the others — trying to force it closed from outside can lead to sync issues.
As of 2024:
react-accessible-accordion is actively maintained, with recent updates addressing React 18 compatibility and TypeScript improvements.
react-collapse is stable and maintained, though updates are infrequent. It works reliably with modern React versions.
react-collapsible shows signs of stagnation. Its last meaningful update was years ago, and it hasn’t been adapted for concurrent rendering patterns. While not officially deprecated, it lacks modern React best practices and should be avoided in new projects unless you’re maintaining legacy code.
✅ Choose react-accessible-accordion
✅ Choose react-collapse
⚠️ Avoid react-collapsible — even for prototypes, prefer react-accessible-accordion or react-collapse. The small convenience isn’t worth technical debt or accessibility gaps.
| Feature | react-accessible-accordion | react-collapse | react-collapsible |
|---|---|---|---|
| ARIA Compliance | ✅ Full, automatic | ❌ None | ❌ None |
| Keyboard Navigation | ✅ Built-in | ❌ Manual | ❌ Manual |
| Animation Technique | CSS max-height | Dynamic height + transform | CSS max-height |
| State Management | ✅ Internal + controlled options | ❌ Fully external | ⚠️ Partial internal |
| Multi-Panel Support | ✅ Yes | ✅ (via your logic) | ✅ Yes |
| Maintenance Status | ✅ Active | ✅ Stable | ⚠️ Stale / Not recommended |
react-accessible-accordion — it’s the only one that gets accessibility right without extra work.react-collapse — if you need pixel-perfect animations and already manage state externally.react-collapsible — outdated, incomplete accessibility, and no compelling advantage over the others.Remember: accessible components aren’t just about compliance — they make your UI more robust, testable, and usable for everyone. Start with the right foundation.
Choose react-accessible-accordion when building public-facing applications where accessibility compliance (WCAG, ADA) is required. It handles ARIA attributes, keyboard navigation, and focus management automatically, reducing the risk of accessibility bugs. Ideal for FAQs, documentation sites, or any interface that must work well with screen readers and keyboards without extra engineering effort.
Choose react-collapse when you need fine-grained control over animation performance and already manage component state externally (e.g., via Redux or context). It provides a lightweight, unstyled collapse primitive that works well for dashboards or internal tools where you can implement accessibility manually — but only if your team has the bandwidth to do so correctly.
Avoid react-collapsible in new projects. While it offers a quick setup with minimal code, it lacks built-in accessibility features, hasn’t been actively maintained, and doesn’t follow modern React patterns. It may seem convenient for prototypes, but the technical debt and accessibility gaps outweigh its simplicity.
In most cases, you no longer need a JS library like this to render fully functional, accessible accordions. For that reason, this project is no longer maintained.
This is because native HTML Disclosure (aka <details>/<summary>) elements are now widely supported.
Native disclosures offer several advantages over any JS-based solutions. For instance:
First, grab the package from npm:
npm install --save react-accessible-accordion
Then, import the editor and use it in your code. Here is a basic example:
import React from 'react';
import {
Accordion,
AccordionItem,
AccordionItemHeading,
AccordionItemButton,
AccordionItemPanel,
} from 'react-accessible-accordion';
// Demo styles, see 'Styles' section below for some notes on use.
import 'react-accessible-accordion/dist/fancy-example.css';
export default function Example() {
return (
<Accordion>
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton>
What harsh truths do you prefer to ignore?
</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>
<p>
Exercitation in fugiat est ut ad ea cupidatat ut in
cupidatat occaecat ut occaecat consequat est minim minim
esse tempor laborum consequat esse adipisicing eu
reprehenderit enim.
</p>
</AccordionItemPanel>
</AccordionItem>
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton>
Is free will real or just an illusion?
</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>
<p>
In ad velit in ex nostrud dolore cupidatat consectetur
ea in ut nostrud velit in irure cillum tempor laboris
sed adipisicing eu esse duis nulla non.
</p>
</AccordionItemPanel>
</AccordionItem>
</Accordion>
);
}
We strongly encourage you to write your own styles for your accordions, but we've published the styles used on our demo page to help you get up and running:
import 'react-accessible-accordion/dist/fancy-example.css';
We recommend that you copy them into your own app and modify them to suit your
needs, particularly if you're using your own classNames.
boolean [optional, default: false]Don't autocollapse items when expanding other items.
boolean [optional, default: false]Allow the only remaining expanded item to be collapsed.
string[] [optional, default: []]Accepts an array of strings and any AccordionItem whose uuid prop matches
any one of these strings will be expanded on mount.
string [optional, default: 'accordion']Class(es) to apply to element.
(string[]) => void [optional]Callback which is invoked when items are expanded or collapsed. Gets passed
uuids of the currently expanded AccordionItems.
string [optional, default: accordion__item]Class(es) to apply to element.
string|number [optional]Recommended for use with onChange. Will be auto-generated if not provided.
boolean [optional]Enables external control of the expansion.
Warning: This may impact accessibility negatively, use at your own risk
string [optional, default: 'accordion__heading']Class(es) to apply to the 'heading' element.
number [optional, default: 3]Semantics to apply to the 'heading' element. A value of 1 would make your
heading element hierarchically equivalent to an <h1> tag, and likewise a value
of 6 would make it equivalent to an <h6> tag.
string [optional, default: 'accordion__button']Class(es) to apply to the 'button' element.
string [optional, default: 'accordion__panel']Class(es) to apply to element.
booleanMake the element have a region role.
({ expanded: boolean, disabled: boolean }): JSX.Element [required](): voidResets the internal counter for Accordion items' identifiers (including id
attributes). For use in test suites and isomorphic frameworks.
Authoring an 'accordion' component to the
WAI ARIA spec can be
complex, but React Accessible Accordion does most of the heavy lifting for
you, including:
aria-expanded, aria-controls,
aria-disabled, aria-hidden and aria-labelledby).role attributes (button, heading, region).tabindex attributes.However, there's still a couple of things you need to keep in mind to remain spec-compliant:
AccordionItemHeading component. If in doubt, use text only.aria-level prop to your AccordionItemHeading
component, especially if you are nesting accordions. This attribute is a
signal used by assistive technologies (eg. screenreaders) to determine which
heading level (ie. h1-h6) to treat your heading as.If you have any questions about your implementation, then please don't be afraid to get in touch via our issues.
RAA supports React 18, and the new out-of-order streaming feature. See the CHANGELOG for details.
Those described by the WAI ARIA spec's description of an 'accordion':
An accordion is a vertically stacked set of interactive headings that each contain a title, content snippet, or thumbnail representing a section of content. The headings function as controls that enable users to reveal or hide their associated sections of content. Accordions are commonly used to reduce the need to scroll when presenting multiple sections of content on a single page.
Components which are "accordion-like" but do not match the WAI ARIA spec's description, as written above. By "accordion-like", we mean components which have collapsible items but require bespoke interactive mechanisms in order to expand, collapse and 'disable' them. This includes (but is not limited to) multi-step forms, like those seen in many cart/checkout flows, which we believe require (other) complex markup in order to be considered 'accessible'. This also includes disclosure widgets.
See "Which design patterns does this component NOT aim to solve?".
Supported browser / device versions:
| Browser | Device/OS | Version |
|---|---|---|
| Mobile Safari | iOS | latest |
| Chrome | Android | latest |
| IE | Windows | 11 |
| MS Edge | Windows | latest |
| Chrome | Desktop | latest |
| Firefox | Desktop | latest |
| Safari | OSX | latest |