Code example
Common baseline
Button role on headers
Each section heading must use role="button" or a <button> element.
aria-expanded on each header button
aria-expanded="true" when the panel is open, aria-expanded="false" when closed.
Header button references its panel
Each header button must reference its panel id via aria-controls.
Toggle panel with Enter/Space
Panels must be toggled open and closed with Enter or Space.
Wrap button in a heading element
Place buttons inside an appropriate h2–h6 heading to maintain document structure.
Arrow key navigation between headers
Down arrow moves to the next header, up arrow moves to the previous header.
Home/End to first/last header
Home navigates to the first header, End navigates to the last header.
Do not use button without a heading
Using a button without a heading wrapper prevents screen readers from navigating the document structure.
Do not force single-expand without notice
If auto-closing other panels, clearly communicate this behavior to users.
Design system implementations
Additional checks
Set id and aria-controls on AccordionSummary
Per WAI-ARIA guidelines, set id on AccordionSummary and aria-controls pointing to the panel id. MUI derives aria-labelledby automatically from these.
Adjust heading level with slotProps.heading
MUI Accordion defaults to h3. Change the heading level using slotProps={{ heading: { component: "h2" } }} to match your page hierarchy.
Code sample
Implementation notes
- –aria-expanded is managed automatically based on the expanded prop state.
- –Set id and aria-controls on AccordionSummary; MUI derives aria-labelledby for the panel automatically.
- –Use slotProps={{ heading: { component: "h3" } }} to adjust heading level to match page structure.
- –Use slotProps={{ transition: { unmountOnExit: true } }} to remove inactive panels from the DOM for better performance.