Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

react-accessible-accordion

springload586kMIT5.0.1TypeScript support: included

Accessible Accordion component for React

react, component, accordion, collapse, accessible, accessibility, wai-aria, aria, a11y

readme

react-accessible-accordion npm

Accessibility status

⚠️ Project status

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:

  • Because there is no JS to download/parse, they are far more performant.
  • They are framework-agnostic, and will work the same way whether you're using React, [other framework], or plain old HTML.
  • Collapsed content can still be found via find-on-page (<key>ctrl</key>/<key>command</key>+<key>f</key>) in supporting browsers, including Chrome.

Demo

Try a demo now.

Usage

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>
    );
}

Styles

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.

Component API

Accordion

allowMultipleExpanded : boolean [optional, default: false]

Don't autocollapse items when expanding other items.

allowZeroExpanded : boolean [optional, default: false]

Allow the only remaining expanded item to be collapsed.

preExpanded: 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.

className : string [optional, default: 'accordion']

Class(es) to apply to element.

onChange : (string[]) => void [optional]

Callback which is invoked when items are expanded or collapsed. Gets passed uuids of the currently expanded AccordionItems.


AccordionItem

className : string [optional, default: accordion__item]

Class(es) to apply to element.

uuid : string|number [optional]

Recommended for use with onChange. Will be auto-generated if not provided.

dangerouslySetExpanded: boolean [optional]

Enables external control of the expansion.

Warning: This may impact accessibility negatively, use at your own risk


AccordionItemHeading

className : string [optional, default: 'accordion__heading']

Class(es) to apply to the 'heading' element.

aria-level : 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.

AccordionItemButton

className : string [optional, default: 'accordion__button']

Class(es) to apply to the 'button' element.


AccordionItemPanel

className : string [optional, default: 'accordion__panel']

Class(es) to apply to element.

region: boolean

Make the element have a region role.


AccordionItemState

children : ({ expanded: boolean, disabled: boolean }): JSX.Element [required]


Helpers

resetNextUuid : (): void

Resets the internal counter for Accordion items' identifiers (including id attributes). For use in test suites and isomorphic frameworks.


Accessibility Best-Practice

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:

  • Applying appropriate aria attributes (aria-expanded, aria-controls, aria-disabled, aria-hidden and aria-labelledby).
  • Applying appropriate role attributes (button, heading, region).
  • Applying appropriate tabindex attributes.
  • Applying keyboard interactivity ('space', 'end', 'tab', 'up', 'down', 'home' and 'end' keys).

However, there's still a couple of things you need to keep in mind to remain spec-compliant:

  • Only ever use phrasing content inside of your AccordionItemHeading component. If in doubt, use text only.
  • Always provide an 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.

FAQs

React 18?

RAA supports React 18, and the new out-of-order streaming feature. See the CHANGELOG for details.

Which design patterns does this component aim to solve?

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.

Which design patterns does this component NOT aim to solve?

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.

How do I disable an item?

See "Which design patterns does this component NOT aim to solve?".

Browser Support

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

changelog

Changelog

All notable changes to this project are documented in this file. This project adheres to Semantic Versioning.

[v5.0.0]

React Accessible Accordion now supports React 18 with its out-of-order streaming feature.

The new out-of-order streaming feature required using React 18's useId hook. This affects the DOM ids that RAA generates, changing from accordion__heading-raa-0 (React 16 and 17) to accordion__heading-:r0: (React 18). Although this change shouldn't affect most users, if you have any code that selects ids with DOM APIs such as document.querySelector() then the : characters will need escaping with \\ eg. document.querySelector('#accordion__heading-\\:r0\\:').

When using older versions of React 16 or 17 the same DOM ids will be generated.

Because of this change in behaviour this is a major version upgrade.

[v4.0.0]

Making role="region" optional on panels.

The new behaviour has no role="region" by default, and developers can opt-in using the region prop as <AccordionItemPanel region>.

The previous behaviour had every panel as a role="region" which created an excessive amount of regions for the screen reader.

Because of this change in behaviour this is a major version upgrade.

[v3.3.0]

Changed

  • Bundle size reduction

[v3.2.0]

Added

  • Use console.error when provided with invalid HTML5 ids

[v3.1.1]

Fixed

  • Use hidden capabilities rather than something needing custom css everywhere.

[v3.1.0]

Added

  • New AccordionItem property: dangerouslySetExpanded enabling external control of the expansion.
  • New AccordionItem property: activeClassName to support expansion-related styles

Fixed

  • hidden support on Microsoft Edge

[v3.0.1]

FIXED

[v3.0.0]

This release is the culmination of a massive amount of work, resulting in some new features and significantly stronger and more reliable WAI ARIA spec compliance. Notably, the project has been migrated from Flow to Typescript, and a full accessibility audit has been performed - revealing a few holes in our compliance which have now been entirely addressed.

Thanks to everyone who has contributed to this release - and not just those who have written code. Contribution by way of issues relating to spec compliance, pull-request commentary, advice and assistance is all greatly appreciated. Thanks also to the patient users who have endured an extended period without a release while we made sure to get this 100% right! Release cadence should return to normal again now.

Breaking Changes - Upgrade Guide:

  1. Rename all of your AccordionItemTitle components to AccordionItemHeading and then nest an AccordionItemButton directly inside of each one. Note that in order for your Accordion to remain spec-compliant, you may not put any other children inside AccordionItemHeading.

     // Before:
     import { AccordionItemTitle } from 'react-accessible-accordion';
    
     const headingBefore = <AccordionItemTitle>Foo</AccordionItemTitle>;
     //  After:
     import {
         AcccordionItemHeading,
         AccordionItemButton,
     } from 'react-accessible-accordion';
    
     const headingAfter = (
         <AccordionItemHeading>
             <AccordionItemButton>Foo</AccordionItemButton>
         </AccordionItemHeading>
     );
  2. Rename all of your AccordionItemBody components to AccordionItemPanel.

     // Before:
     import { AccordionItemBody } from 'react-accessible-accordion';
    
     const panelBefore = (
         <AccordionItemBody>
             Voluptate elit eiusmod laborum proident esse officia dolor laboris
             laboris amet nulla officia cillum.
         </AccordionItemBody>
     );
     // After:
     import { AccordionItemPanel } from 'react-accessible-accordion';
    
     const panelAfter = (
         <AccordionItemPanel>
             Voluptate elit eiusmod laborum proident esse officia dolor laboris
             laboris amet nulla officia cillum.
         </AccordionItemPanel>
     );
  3. Remove all instances of hideBodyClassName. This prop is no longer valid, as AccordionItemPanel components are now hidden without additional styling. If you must have a different className prop when an item is collapsed, then you may leverage the new AccordionItemState component.

     // Before
     import { AccordionItemPanel } from 'react-accessible-accordion';
    
     const panelBefore = (
         <AccordionItemPanel className="foo" hideBodyClassName="foo--hidden" />
     );
     // After:
     import {
         AccordionItemPanel,
         AccordionItemState,
     } from 'react-accessible-accordion';
    
     const panelAfter = (
         <AccordionItemState>
             {({ expanded }) => (
                 <AccordionItemPanel
                     className={expanded ? 'foo' : 'foo foo--hidden'}
                 />
             )}
         </AccordionItemState>
     );
  4. Remove all instances of AccordionItem’s expanded prop and instead use Accordion’s preExpanded prop. Note that this means that ‘controlled’ accordions are no longer a supported pattern. Please raise an issue if you have a use-case which calls for the ability to manually control expanded state.

     // Before
     import { Accordion, AccordionItem } from 'react-accessible-accordion';
    
     const accordionBefore = (
         <Accordion>
             <AccordionItem expanded />
         </Accordion>
     );
     // After:
     import { Accordion, AccordionItem } from 'react-accessible-accordion';
    
     const accordionAfter = (
         <Accordion preExpanded={['foo']}>
             <AccordionItem uuid="foo" />
         </Accordion>
     );
  5. Remove all instances of Accordion’s accordion prop. Instead, use a combination of allowZeroExpanded and allowMultipleExpanded props to suit your requirements. If you were not explicitly setting accordion to false then you probably are not required to make any changes here.

     // Before
     import { Accordion } from 'react-accessible-accordion';
    
     const accordionBefore = <Accordion accordion={false} />;
     // After:
     import { Accordion } from 'react-accessible-accordion';
    
     const accordionAfter = <Accordion allowMultipleExpanded />;
  6. Upgrade to React v16.3+

  7. Remove your minimal-example.css import. These styles only applied display: none to panels when collapsed, but browsers apply these styles to elements with the hidden attribute, which the AccordionItemPanel component now has (when collapsed).

Added

  • Added AccordionItemButton component.
  • Added AccordionItemState component.
  • Added allowZeroExpanded prop to Accordion.
  • Added allowMultipleExpanded prop to Accordion.
  • Out-of-the-box Typescript support.
  • Integration tests to explicitly assert every line of the WAI ARIA 'Accordion' spec.
  • Additional keyboard functionality (Up, Down, Left, Right, Home, End).

Changed

  • Renamed AccordionItemTitle to AccordionItemHeading to be consistent with the language used in the WAI ARIA spec.
  • Renamed AccordionItemBody to AccordionItemPanel to be consistent with the language used in the WAI ARIA spec.
  • Updated AccordionItemPanel to have a hidden attribute.
  • Roles and aria attributes all audited and updated to match the WAI ARIA spec.
  • Update onChange to always be called with an array of the currently expanded items.

Fixed

  • Fixes SSR (server-side rendering).
  • Fixes incorrect roles and attributes as per the WAI ARIA spec.

Removed

  • Removed Flow support (but we hope to reinstate typing in the future. Track progress here).
  • Removed undocumented expanded mechanism for AccordionItems.
  • Removed undocumented disabled mechanism for AccordionItems.
  • Remove hideBodyClassName prop.

[v2.4.5]

Fixed

  • Fixes SSR.

[v2.4.4]

Fixed

  • Fixes performance issue with not re-instantiating render-prop callbacks on each re-render.

[v2.4.3]

Fixed

  • Fixes issue with spacebar scrolling the page (see PR#99)
  • Fixes IE compatibility by replacing uses of Array.prototype.find.

[v2.4.2]

Changed

  • Removes invalid test
  • Minor change to package.json to remove some redundant Jest config.
  • Upgrade one forgotten devDependency.

Fixed

  • Emergency bug fix to remove asyc/await from the code (see PR#95)

[v2.4.1]

This release brings support for React 16.3+ by way of some minor refactoring to remove deprecated lifecycle methods.

Changed

  • Replace deprecated lifecycle methods 'componentWillReceiveProps', 'componentWillUpdate' and 'componentWillMount'.
  • Updated unstated (internal dependency) to latest major release.
  • Updated all devDependencies.

[v2.4.0]

Added

Fixed

[v2.3.1]

Fixed

  • Add dist folder to list of Flow ignores, so Flow doesn’t error after a build.
  • Issue with babel helpers. Just reverted commit 6f9f2c324a6fad4a35a84307241f4f710407f242 for now.

Changed

  • Removed a couple of old npm scripts from the days before we introduced rollup to the build pipeline.
  • Upgraded a bunch of devDependencies, including Webpack which required a bit of a config refactor.

[v2.3.0]

Changed

  • Refactored to use unstated for state-management instead of mobx + mobx-react, cutting the size of the bundle by approximately 60% 🎉.

[v2.2.1]

Changed

  • Fixes mixed up filenames in the README

[v2.2.0]

Added

  • Demo styles added to the bundle as two optional files:
    • minimal-example.css: 'Minimal' theme - hide/show the AccordionBody component
    • fancy-example.css: 'Fancy' theme - boilerplate styles for all components, as seen on our demo

[v2.1.0]

Added

  • Publish flow types.

Changed

  • Update all React components to accept arbitrary HTMLDivElement props (eg. 'lang', 'role' etc).
  • Upgrade all dev-dependencies except the eslint configs.
  • Replace snapshot tests with explicit assertions in AccordionItemBody and AccordionItemTitle.
  • Add specific assertions to tests in accordionStore.
  • Minor syntax change in AccordionItemBody

[v2.0.0]

Version 2.0 represents a total refactor, with a new context-based approach which should make this library more flexible, more maintainable and more comprehensively testable.

As this is a major release, users should expect some breaking changes - though they should be limited to the removal of the activeItems prop (read more below).

Added

Fixed

  • Defect where controlled components' props were overridden by React.Children.map (https://github.com/springload/react-accessible-accordion/issues/33).
  • Defect where accordion crashed with unexpected children types (https://github.com/springload/react-accessible-accordion/issues/45).
  • Defect where React Accessible Accordion's components could not be extended.
  • Defect where the children of Accordion or AccordionItem could not be arbitrary.
  • Defect where AccordionItem had to be a child of Accordion (as opposed to to an arbitrary-level descendant).
  • Defect where AccordionItemBody and AccordionItemTitle had to be children of AccordionItem (as opposed to arbitrary-level descendants).

Removed:

  • 🚨 Breaking change 🚨 activeItems property is no longer supported.

Control at the Accordion level (via the activeItems prop) and AccordionItem level (via the expanded prop) fought against one another, and choosing which control mechanism to give preference to would have been an arbitrary decision - and whichever way we went, we would have had test cases which demonstrated unusual/unpredictable behaviour. The activeItems mechanism was the obvious one to remove - it was arguably the "less React-y way", and we considered it more of a convenience than a feature. Crucially though, it fought too hard against the new architecture of the library, and keeping it would have prevented us enabling lots of other new features or resolving some of the issues that our users had raised.

If you're currently using activeItems, you're upgrade path might look like this:

const items = ['Foo', 'Bar'];
const activeItems = [0];

return (
-    <Accordion activeItems={activeItems} />
+    <Accordion />
        {activeItems.forEach((item, i) => (
-            <AccordionItem key={item}>{item}</AccordionItem>
+            <AccordionItem key={item} expanded={activeItems.includes(i)}>{item}</AccordionItem>
        )}
    </Accordion>
);

Please don't hesitate to reach out to one of the maintainers (or raise an issue) if you're having trouble upgrading - we're happy to help!

[v1.0.1]

[v1.0.0]

NB: This version is backward compatible. It's just bumping to 1.0 to represent maturity rather than API changes.

[v0.6.0]

[v0.5.0]

[v0.4.0]

  • Supports React 15.5+

[v0.3.0]

  • No warnings when you have only one item in the accordion

[v0.2.0]

  • Possibility to have extra blocks in AccordionItem

[v0.1.2]

  • Accordion mode / Collapse mode
  • Possibility to pre expand items
  • 100% coverage with unit tests
  • Possibility to customise CSS.
  • Clean CSS for the demo/github page.

[vx.y.z] Template from http://keepachangelog.com/

Added

  • Something was added to the API / a new feature was introduced.

Changed

Fixed

Removed