Accessibility (a11y)
ARIA attributes, keyboard navigation, screen reader support, and testing.
Overview
Accessibility ensures React apps are usable by everyone, including people with disabilities.
Key Concepts
- Semantic HTML — Use proper HTML elements for meaning
- ARIA Attributes — Enhance accessibility when HTML isn't enough
- Keyboard Navigation — Support tab, enter, escape, arrow keys
- Screen Readers — Announce dynamic content changes
- Focus Management — Maintain logical focus order
Code Examples
function AccessibleModal({ isOpen, onClose, title, children }) {
const closeRef = useRef(null);
useEffect(() => {
if (isOpen) closeRef.current?.focus();
}, [isOpen]);
useEffect(() => {
const handleEscape = (e) => {
if (e.key === 'Escape') onClose();
};
if (isOpen) {
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}
}, [isOpen, onClose]);
if (!isOpen) return null;
return (
<div
className="modal-overlay"
onClick={onClose}
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
>
<div className="modal-content" onClick={e => e.stopPropagation()}>
<h2 id="modal-title">{title}</h2>
{children}
<button ref={closeRef} onClick={onClose} aria-label="Close modal">
×
</button>
</div>
</div>
);
}
function AccessibleTabs({ tabs, panels }) {
const [activeIndex, setActiveIndex] = useState(0);
const handleKeyDown = (e) => {
if (e.key === 'ArrowRight') setActiveIndex(i => (i + 1) % tabs.length);
if (e.key === 'ArrowLeft') setActiveIndex(i => (i - 1 + tabs.length) % tabs.length);
};
return (
<div>
<div role="tablist" onKeyDown={handleKeyDown}>
{tabs.map((tab, index) => (
<button
key={tab.id}
role="tab"
aria-selected={index === activeIndex}
aria-controls={`panel-${tab.id}`}
tabIndex={index === activeIndex ? 0 : -1}
onClick={() => setActiveIndex(index)}
>
{tab.label}
</button>
))}
</div>
{panels.map((panel, index) => (
<div
key={panel.id}
role="tabpanel"
id={`panel-${panel.id}`}
hidden={index !== activeIndex}
>
{panel.content}
</div>
))}
</div>
);
}
Practice
Audit and fix accessibility issues in a React component library.