Accordion
Table of Contents
For this accordion, I used the Accordion (Sections with Show/Hide Functionality)-design pattern Opens an external site from WAI-ARIA Authoring Practices. I've written a blog post Opens an external site explaining the pattern a bit more.
This Accordion component takes a title as props and displays the children of the component as the content
Cat ipsum dolor sit amet, i love cats i am one wake up scratch humans leg for food then purr then i have a and relax.
In WAI-ARIA Design Patterns, the keyboard shortcuts and ARIA states, properties and roles are defined. I'll introduce them in the next sections. Then I'll show the source code for the Accordion-component.
Keyboard Shortcuts
Key | Behaviour |
---|---|
Enter or Spacebar | When focus is on the accordion header, opens or closes that accordion. |
Tab | Moves focus for the next focusable element. |
Shift + Tab | Moves focus for the next previous element. |
There are also optional keyboard shortcuts, which will not be implemented in this example:
Key | Behaviour |
---|---|
Up Arrow | When focused to an accordion header, used for navigating from that header to the next |
Down Arrow | When focused to an accordion header, used for navigating from that header to the previous. |
Home | When focused to an accordion header, used for navigating to the first accordion header. |
End | When focused to an accordion header, used for navigating to the last accordion header. |
ARIA-states, properties, and roles
Each accordion header's title should be contained within an element with a `button '-role. In the example, this is done with a button
-element.
This button
-element should be then wrapped into an element that has the role of heading
and aria-level
set. In the example, we use an h2
element. There should be anything else except the button inside the heading. The header's button
element should have aria-disabled
set to true if the panel associated with it is open and not closable.
The last thing for the accordion header is an aria-expanded
-attribute set to the button
. Its value depends on the accordion panel's visibility; if it is visible, then the value is true
, and if not, then false
.
WAI-ARIA Authoring Practices mention adding aria-controls
with the id of the accordion panel. There is, however, something to note about the aria-controls
; it is currently supported only in JAWS.
The accordion panels' containers can have a role region
and aria-labelledby
referencing the id of the button in the accordion header. However, note that if there are more than approximately six accordions expandable simultaneously, the region
-role shouldn't be used. Too many regions on the same page are too much.
Source Code
Accordion
interface AccordionProps {
title: string;
}
const Accordion: FunctionComponent<AccordionProps> = ({ title, children }) => {
const [isOpen, setIsOpen] = useState(false);
const handleOpen = () => setIsOpen(!isOpen);
return (
<section className="accordion-container">
<div id="accordion-title">
<h2>
<button
id="accordion-button"
aria-expanded={isOpen}
onClick={handleOpen}
aria-controls="accordion-content"
>
<span>{isOpen ? "-" : "+"} </span>
{title}
</button>
</h2>
</div>
<div
id="accordion-content"
aria-labelledby="accordion-button"
hidden={!isOpen}
role="region"
>
{children}
</div>
</section>
);
};
CSS
#accordion-content {
padding: 1rem 1.5rem;
border-top: 0.1rem solid var(--color-text);
background-color: var(--color-bakcground);
}
#accordion-button {
background-color: transparent;
border-style: none;
padding: 1rem 1.5rem;
font-size: 1.5rem;
width: 100%;
text-align: left;
display: block;
margin: 0;
color: var(--color-text);
}
.accordion-container {
border: 0.2rem solid var(--color-text);
width: 25rem;
max-width: 90%;
font-size: 1.5rem;
}
#accordion-title {
outline: none;
background-color: var(--color-bakcground);
}
#accordion-title > h2 {
margin: 0;
padding: 0;
outline: none;
}