Install the axe DevTools browser extension. Open PixelCraft → run the audit. Screenshot 23 violations. Categorize: keyboard (8), contrast (6), ARIA (5), focus (4). Fix them all.
// Toolbar: keyboard navigable
// with arrow keys
function Toolbar({
tools, activeTool, onToolSelect
}: ToolbarProps) {
const handleKeyDown = (
e: React.KeyboardEvent,
index: number
) => {
if (e.key === 'ArrowDown') {
e.preventDefault();
const next =
(index + 1) % tools.length;
document.getElementById(
`tool-${tools[next].id}`)
?.focus();
}
if (e.key === 'ArrowUp') {
e.preventDefault();
const prev = (index - 1
+ tools.length) % tools.length;
document.getElementById(
`tool-${tools[prev].id}`)
?.focus();
}
};
return (
<nav role="toolbar"
aria-label="Image editing tools">
{tools.map((tool, index) => (
<button
key={tool.id}
id={`tool-${tool.id}`}
role="radio"
aria-checked={
activeTool === tool.id}
tabIndex={
activeTool === tool.id
? 0 : -1}
onKeyDown={(e) =>
handleKeyDown(e, index)}
onClick={() =>
onToolSelect(tool.id)}>
<span aria-hidden="true">
{tool.icon}</span>
<span className="sr-only">
{tool.name}</span>
</button>
))}
</nav>
);
}
// Announce filter changes to
// screen readers
<div
role="status"
aria-live="polite"
className="sr-only">
{`Brightness set to ${brightness}`}
</div>
// aria-live="polite":
// announces when idle (non-urgent)
// aria-live="assertive":
// announces immediately (errors)
// sr-only class (Tailwind):
// Visually hidden, but screen
// readers can still read it.
function Modal({
isOpen, onClose, children
}: ModalProps) {
const closeRef =
useRef<HTMLButtonElement>(null);
const previousFocus =
useRef<HTMLElement | null>(null);
useEffect(() => {
if (isOpen) {
// Save current focus
previousFocus.current =
document.activeElement
as HTMLElement;
// Move focus into modal
closeRef.current?.focus();
} else {
// Return focus when closing
previousFocus.current?.focus();
}
}, [isOpen]);
if (!isOpen) return null;
return (
<div
role="dialog"
aria-modal="true"
aria-label="Export settings">
<button
ref={closeRef}
onClick={onClose}>
Close
</button>
{children}
</div>
);
}
// Fix: adjust all low-contrast text
// ❌ Before: #999 on #fff = 2.85:1
// (fails AA for normal text)
// ✅ After: #595959 on #fff = 7.0:1
// (passes AA and AAA)
// Check with: WebAIM Contrast Checker
// Target: 4.5:1 normal, 3:1 large
// Re-run axe audit:
// 23 violations → 0 violations ✅
git switch -c a11y/PIXELCRAFT-089-accessibility
git add src/
git commit -m "Fix 23 a11y violations: WCAG 2.1 AA (PIXELCRAFT-089)"
git push origin a11y/PIXELCRAFT-089-accessibility
# PR → Review → Merge → Close ticket ✅
Universal design benefits everyone.
The web was designed to be accessible from birth. Good accessibility IS good design. Every accessibility feature has mainstream benefits.