React
React Accessibility
Build inclusive DataFlow components that screen readers understand, keyboard navigation works perfectly, and every user can access your analytics dashboard.
Accessibility isn't an afterthought. It's the difference between a dashboard that works for everyone and one that excludes millions of users. React gives you the tools to build inclusive interfaces — but you need to know how to use them.The Hidden Users
The DataFlow team discovered something during user testing. Their beautiful analytics dashboard was completely unusable for Sarah, who navigates with a keyboard due to motor limitations. The charts had no text alternatives. The filters couldn't be reached with Tab. The color-coded status indicators meant nothing to users with color blindness. Accessibility means making your app work for everyone. Screen reader users, keyboard-only users, users with visual impairments, users with cognitive differences. When you build accessible React components, you're not just checking a compliance box — you're expanding your user base.// BAD: Inaccessible button
function DeleteButton() {
return (
<div onClick={() => deleteUser()}>
❌
</div>
);
}What just happened?
This button can't be reached with keyboard navigation, screen readers don't know what it does, and the emoji means different things in different cultures. Try tabbing to it — you can't.
Semantic HTML Foundation
Accessibility starts with using the right HTML elements. React components should use semantic tags that browsers and assistive technologies understand. Abutton is better than a div with click handlers.
// GOOD: Accessible DataFlow components
function StatsCard({ title, value, trend }) {
return (
<article role="region" aria-labelledby="stat-title">
<h3 id="stat-title">{title}</h3>
<p>{value}</p>
<span aria-label={`Trend: ${trend > 0 ? 'increasing' : 'decreasing'}`}>
{trend > 0 ? '↗️' : '↘️'}
</span>
</article>
);
}What just happened?
The article tag creates a landmark, the h3 provides structure, and aria-label gives screen readers meaningful descriptions of the trend arrows. Try this: use a screen reader to navigate this component.
ARIA Attributes
ARIA (Accessible Rich Internet Applications) attributes tell assistive technologies what your components do. They're like subtitles for screen readers. React supports all ARIA attributes, but you need to know which ones to use when.aria-label
Provides accessible names for elements without visible text
aria-describedby
References elements that describe the current element
aria-expanded
Indicates if collapsible elements are open or closed
role
Defines what an element is or does when semantics aren't clear
// DataFlow filter dropdown with ARIA
function FilterDropdown({ options, onSelect }) {
const [isOpen, setIsOpen] = useState(false);
return (
<div role="combobox" aria-expanded={isOpen}>
<button
aria-haspopup="listbox"
aria-controls="filter-list"
onClick={() => setIsOpen(!isOpen)}
>
Filter Data
</button>
{isOpen && (
<ul id="filter-list" role="listbox">
{options.map(option => (
<li key={option} role="option">{option}</li>
))}
</ul>
)}
</div>
);
}Keyboard Navigation
Your DataFlow dashboard must work without a mouse. Users navigate with Tab, Enter, Space, and arrow keys. React doesn't handle this automatically — you need to manage focus states and keyboard event handlers.// Keyboard-accessible data table
function DataTable({ transactions }) {
const [focusedRow, setFocusedRow] = useState(0);
const handleKeyDown = (e) => {
if (e.key === 'ArrowDown') {
setFocusedRow(prev =>
Math.min(prev + 1, transactions.length - 1)
);
}
if (e.key === 'ArrowUp') {
setFocusedRow(prev => Math.max(prev - 1, 0));
}
};
return (
<table role="table" onKeyDown={handleKeyDown}>
<tbody>
{transactions.map((tx, index) => (
<tr
key={tx.id}
tabIndex={index === focusedRow ? 0 : -1}
style={{
background: index === focusedRow ? '#eff6ff' : 'white'
}}
>
<td>{tx.amount}</td>
<td>{tx.description}</td>
</tr>
))}
</tbody>
</table>
);
}Focus Management
Focus is like a cursor for keyboard users. When you show a modal, focus should move to it. When you close a dropdown, focus returns to the trigger button. React gives youuseRef to control focus programmatically.
Focus Trap Warning
Modal dialogs must trap focus inside them. Without this, keyboard users can tab behind the modal and get lost. Libraries like react-focus-trap handle this complexity for you.
// Modal with focus management
function DeleteConfirmModal({ isOpen, onClose }) {
const firstFocusRef = useRef(null);
const lastFocusRef = useRef(null);
useEffect(() => {
if (isOpen) {
firstFocusRef.current?.focus();
}
}, [isOpen]);
const handleTabKey = (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstFocusRef.current) {
e.preventDefault();
lastFocusRef.current?.focus();
} else if (!e.shiftKey && document.activeElement === lastFocusRef.current) {
e.preventDefault();
firstFocusRef.current?.focus();
}
}
};
if (!isOpen) return null;
return (
<div role="dialog" aria-modal="true" onKeyDown={handleTabKey}>
<h2>Delete Transaction?</h2>
<button ref={firstFocusRef} onClick={onClose}>
Cancel
</button>
<button ref={lastFocusRef}>Delete</button>
</div>
);
}Form Accessibility
DataFlow forms need proper labels, error messaging, and validation feedback. Every input must have an associated label. Error messages should be announced to screen readers when they appear.// Accessible DataFlow search form
function SearchForm() {
const [query, setQuery] = useState('');
const [error, setError] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (!query.trim()) {
setError('Search query is required');
return;
}
setError('');
// Perform search
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="search-input">
Search Transactions
</label>
<input
id="search-input"
value={query}
onChange={(e) => setQuery(e.target.value)}
aria-describedby={error ? "search-error" : undefined}
aria-invalid={!!error}
/>
{error && (
<div id="search-error" role="alert" aria-live="polite">
{error}
</div>
)}
<button type="submit">Search</button>
</form>
);
}What just happened?
The htmlFor attribute connects the label to the input. aria-describedby links the error message. role="alert" announces errors immediately. Try this: submit the form without typing anything.
Color and Contrast
Color alone shouldn't convey information. Your DataFlow status indicators need text labels or patterns, not just green/red colors. Contrast ratios must meet WCAG guidelines — at least 4.5:1 for normal text, 3:1 for large text.Testing Tools
Use browser DevTools to audit accessibility. Chrome's Lighthouse includes accessibility checks. Tools like axe-core can catch issues during development. But nothing replaces testing with actual users.
Quiz
1. The DataFlow team needs to make a chart icon accessible to screen readers. What does the aria-label attribute do?
2. Which attributes make error messages immediately announced to screen readers in React forms?
3. Which practice breaks keyboard accessibility in DataFlow components?
Up Next: React Performance Audit
Debug slow DataFlow renders, identify performance bottlenecks, and use React DevTools Profiler to optimize your dashboard for thousands of concurrent users.