Expandable components use aria-expanded
Why it matters
An accordion section that shows or hides content via CSS display: none / block toggling — but has no aria-expanded on the trigger button — is invisible in state to screen readers. The screen reader announces 'button: FAQ: What is your refund policy?' whether the section is open or closed. Users who want to collapse an open section have no way to confirm its current state before clicking. WCAG 2.2 SC 4.1.2 (Name, Role, Value) requires the state of UI components to be programmatically determinable. Section 508 2018 Refresh 502.3.4 covers programmatic state. The ARIA disclosure widget pattern specifies aria-expanded on the controlling button and id/aria-controls linking the button to its panel.
Severity rationale
Medium because absent `aria-expanded` removes state awareness from screen reader users, degrading their ability to navigate and manage accordions and disclosure widgets.
Remediation
Add aria-expanded to the trigger button and link it to the controlled panel with aria-controls. Ensure the panel is hidden in a way that assistive technology respects — use hidden attribute or display: none, not visibility: hidden or opacity: 0.
const Accordion = ({ items }: { items: { id: string; title: string; body: string }[] }) => {
const [openId, setOpenId] = useState<string | null>(null);
return (
<div className="accordion">
{items.map(item => (
<div key={item.id} className="accordion-item">
<h3>
<button
aria-expanded={openId === item.id}
aria-controls={`panel-${item.id}`}
id={`btn-${item.id}`}
onClick={() => setOpenId(id => id === item.id ? null : item.id)}
>
{item.title}
</button>
</h3>
<div
id={`panel-${item.id}`}
role="region"
aria-labelledby={`btn-${item.id}`}
hidden={openId !== item.id}
>
<p>{item.body}</p>
</div>
</div>
))}
</div>
);
};
Using hidden (not CSS display: none alone) ensures assistive technology does not read the panel content when collapsed. If using CSS for animation, remove hidden but add aria-hidden={openId !== item.id} to maintain the programmatic state signal.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Accessibility Basics Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- wcag:2.2 · 4.1.2 — Name, Role, Value
- section-508:2018-refresh · 502.3.4 — Values
Taxons
History
- 2026-04-18·v1.0.0·Initial import from accessibility-basics·automated