npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-aria-accordion

v1.0.7

Published

React accordion component that follows WAI-ARIA practices

Downloads

194

Readme

React Aria Accordion

This accordion component aims to follow the guidelines set out in the WAI-ARIA Authoring Practices 1.1 and uses the render props pattern to be as flexible as possible.

It is purposefully missing the ability for a section to be auto collapsed on expanding another. Read Design decisions for more information.

Demo

Demo

Table of contents

Installation

npm install react-aria-accordion

Example usage

Given the flexible nature of the component it would be best to wrap each component and style them as is appropriate for your use case.

// Accordion/Accordion
import Accordion from 'react-aria-accordion';

const MyAccordion = ({ children, ...rest }) => (
  <Accordion>
    {() => <div>{children}</div>}
  </Accordion>
);

export default MyAccordion;

// Accordion/Section
import { Section } from 'react-aria-accordion';

const MySection = ({ onToggle, defaultExpanded, children }) => (
  <Section onToggle={onToggle} defaultExpanded={defaultExpanded}>
    {({ getSectionProps }) => <div {...getSectionProps()}>{children}</div>}
  </Section>
);

export default MySection;

// Accordion/Header
import { Header } from 'react-aria-accordion';

// Using native html elements

const MyHeader = ({ title }) => (
  <Header>
    {({ getButtonToggleProps }) => (
      <h1>
        <button {...getButtonToggleProps()}>{title}</button>
      </h1>
    )}
  </Header>
);

// Using custom html elements

const MyHeader = ({ title }) => (
  <Header headingLevel={1}>
    {({ getHeadingProps, getElementToggleProps }) => (
      <div {...getHeadingProps()}>
        <div {...getElementToggleProps()}>{title}</div>
      </div>
    )}
  </Header>
);

export default Header;

// Accordion/Panel
import { Panel } from 'react-aria-accordion';

const MyPanel = ({ children }) => (
  <Panel>
    {({ getPanelProps }) => (
      <div {...getPanelProps()}>
        {children}
      </div>
    )}
  </Panel>
);

export default MyPanel;

// Accordion/index
export { default } from './Accordion';
export { default as Section } from './Section';
export { default as Header } from './Header';
export { default as Panel } from './Panel';

This would allow the following:

import Accordion, { Section, Header, Panel } from './Accordion';

<Accordion>
  <Section
    defaultExpanded
    onToggle={
      (nextExpanded) => console.log(`First section is ${nextExpanded ? 'expanded' : 'collapsed'}`)
    }
  >
    <Header title="Names" />
    <Panel>
      {listOfNames}
    </Panel>
  </Section>
  <Section>
    <Header title="Contact details" />
    <Panel>
      {listOfContactDetails}
    </Panel>
  </Section>
  <Section>
    <Header title="Other" />
    <Panel>
      {other}
    </Panel>
  </Section>
</Accordion>

Server Sider Rendering (SSR)

An additional initialiseForSsr function is required when using SSR so that the DOM matches when using client hydration:

import { renderToString } from 'react-dom/server';
import { initialiseForSsr } from 'react-aria-accordion';

initialiseForSsr();
renderToString(<App />);

Using <Header /> correctly

The title for the accordion section must be wrapped in exactly one button and one heading. The following 2 examples offer the same semantics. Where possible use native html elements.

const header = (
  <Header>
    {({ getButtonToggleProps }) => (
      <h2>
        <button {...getButtonToggleProps()}>Title</button>
      </h2>
    )}
  </Header>
);

const header = (
  <Header headingLevel={2}>
    {({ getHeadingProps, getElementToggleProps }) => (
      <div {...getHeadingProps()}>
        <div {...getElementToggleProps()}>Title</div>
      </div>
    )}
  </Header>
);

If you want to include a menu next to the title, then make sure the menu is not inside the heading element.

const header = (
  <Header>
    {({ getButtonToggleProps }) => (
      <Fragment>
        <h2>
          <button {...getButtonToggleProps()}>Title</button>
        </h2>
        <Menu />
      </Fragment>
    )}
  </Header>
);

API

<Accordion />

children

function({}) | required

This is called with an object.

| Property | Type | Description | |-----------------------|--------------|-------------------------| | expandAllSections | function() | Expands all sections. | | collapseAllSections | function() | Collapses all sections. |

<Section />

defaultExpanded

boolean | defaults to false

This is the initial expanded value.

expanded

boolean | control prop

onToggle

function(nextExpanded: boolean) | defaults to undefined

children

function({}) | required

This is called with an object.

| Property | Type | Description | |-------------------|---------------------------|---------------------------------------------------------------| | getSectionProps | function(props: object) | Returns the props you should apply to the element you render. | | expanded | boolean | The expanded state of the section. |

<Header />

disabled

boolean | defaults to false

headingLevel

number | defaults to 1

children

function({}) | required

This is called with an object.

| Property | Type | Description | |-------------------------|---------------------------|--------------------------------------------------------------------------------------------------| | getHeadingProps | function(props: object) | Returns the props you should apply to the heading element you render when not using <h# />. | | getButtonToggleProps | function(props: object) | Returns the props you should apply to the toggle element you render when using <button />. | | getElementToggleProps | function(props: object) | Returns the props you should apply to the toggle element you render when not using <button />. | | expanded | boolean | The expanded state of the section. |

<Panel />

children

function({}) | required

This is called with an object.

| Property | Type | Description | |-----------------|---------------------------|---------------------------------------------------------------| | getPanelProps | function(props: object) | Returns the props you should apply to the element you render. | | expanded | boolean | The expanded state of the section. |

initialiseForSsr

function()

See Server Side Rendering (SSR) for more details.

Design decisions

No auto collapse behaviour

The aim of this component is to be used in projects to help developers feel confident they are making their websites as accessible as possible using relevant aria-* properties.

Automatic collapsing of sections can disorientate some users, particularly if scroll behaviour is also associated. For example, if a user is using magnification software they may not realise that expanding one section has collapsed another.

Data presented within a section may be comparable with another, therefore having more than one section expanded at a time may be a useful feature for your users.

Collapsing and expanding multiple sections manually may make your website difficult to use, so this component provides the functionality to collapse and expand all sections at once. Given this behaviour will need to be triggered by a user there are less usability concerns.

Technical decisions

Why expanded is available for Section, Header & Panel

The reason the same render prop is available is so that it's possible to wrap each component as shown in Example usage without having to pass your own expanded prop to Header and Panel.

Using querySelectorAll in <Accordion />

You may think that using a lifecycle method like componentWillMount in <Section /> would suffice, however it wouldn't cope with the following scenario:

<Accordion>
  <Section>A</Section>
  {showSection ? <Section>B</Section> : null}
  <Section>C</Section>
</Accordion>

If showSection starts as false and switches to true later, then componenetWillMount will fire for Section B, leaving the accordion no ability to know the ordering of the sections. Having to manually specify the order of a <Section /> would be a burden on the developer.

Contributors

Thanks goes to these wonderful people (emoji key):

| Kenneth Gray💻 📖 ⚠️ 💡 | Koji Wakayama💻 | | :---: | :---: |

This project follows the all-contributors specification. Contributions of any kind are welcome!