Comprehensive Rules for building WCAG-compliant, keyboard-operable, screen-reader-friendly web applications.
You know that moment when you watch a user struggle with your interface—clicking desperately where there's no visual feedback, trapped in a focus cycle they can't escape, or worse, completely unable to complete their task? That's not just bad UX. That's 1.3 billion people worldwide hitting walls your code created.
Here's what actually happens when accessibility becomes an afterthought:
Legal Reality: ADA lawsuits hit 4,605 companies in 2023, with settlements averaging $75,000-$400,000. The EU's European Accessibility Act takes effect in 2025 with penalties up to 4% of annual revenue.
Development Hell: Retrofitting accessibility into existing codebases takes 3-5x longer than building it in from the start. Your team will spend weeks untangling focus management, rewriting form validation, and debugging screen reader interactions.
User Experience Breakdown: Screen readers announce "clickable clickable clickable" for your custom button divs. Keyboard users get trapped in your modal. Color-blind users can't distinguish your error states. These aren't edge cases—they're predictable failures.
These Cursor Rules transform accessibility from a compliance checkbox into a streamlined development workflow. Instead of wrestling with WCAG documentation and hunting down violations after the fact, you get intelligent code generation that builds accessibility in from the first keystroke.
The system covers everything from semantic HTML structure to complex interactive patterns, with built-in testing integration and framework-specific optimizations for React, Angular, and Vue.
// Your PM just discovered accessibility requirements exist
<div className="button" onClick={handleClick}>
<span style={{color: '#ff0000'}}>Error: Fix this!</span>
</div>
Result: 3 weeks of emergency refactoring, failed audits, and frustrated developers trying to make screen readers work with non-semantic markup.
// Generated with proper semantics from day one
<button
aria-busy={loading}
disabled={loading}
className="error-state"
>
{loading && <Spinner aria-hidden="true" />}
<span className="sr-only">Error: </span>
Fix this issue
</button>
Result: Zero accessibility debt, automated testing passes, and screen readers work perfectly on first deployment.
Stop spending 3x the effort fixing accessibility issues after launch. The rules generate semantically correct, WCAG-compliant code from the start, including proper ARIA attributes, keyboard navigation, and focus management.
Built-in CI pipeline configuration with axe-core and Pa11y blocks problematic code from reaching production. Your team catches violations before they become expensive fixes.
Get React hooks for focus management, Vue composables for ARIA state, and Angular directives for keyboard navigation—all following established accessibility patterns your team can trust.
Accessibility features that don't slow down your app. The rules include performance optimizations like debounced live region updates and efficient focus management that maintains your performance budgets.
Instead of manually wiring up labels, error states, and validation:
// What you type
const LoginForm = () => {
// What Cursor generates with these rules
const LoginForm = () => {
const [errors, setErrors] = useState<Record<string, string>>({});
return (
<form onSubmit={handleSubmit} noValidate>
<fieldset>
<legend>Login to your account</legend>
<label htmlFor="email">Email address</label>
<input
id="email"
type="email"
required
aria-invalid={errors.email ? 'true' : undefined}
aria-describedby={errors.email ? 'email-error' : undefined}
onBlur={validateField}
/>
{errors.email && (
<div id="email-error" role="alert">
{errors.email}
</div>
)}
</fieldset>
</form>
);
};
No more broken focus traps or confused screen readers:
// Auto-generated accessible modal pattern
const Modal = ({ isOpen, onClose, children }) => {
const previousFocus = useRef<HTMLElement>();
useEffect(() => {
if (isOpen) {
previousFocus.current = document.activeElement as HTMLElement;
// Focus first focusable element
} else if (previousFocus.current) {
previousFocus.current.focus();
}
}, [isOpen]);
return (
<dialog
open={isOpen}
aria-modal="true"
onKeyDown={(e) => e.key === 'Escape' && onClose()}
>
{children}
</dialog>
);
};
Building accessible data tables, carousels, and navigation components becomes straightforward with pre-configured ARIA patterns and keyboard interaction handlers.
# Add to your .cursorrules file
curl -o .cursorrules https://your-rules-source/accessible-web-app-rules
// package.json
{
"scripts": {
"a11y": "axe-core ./dist && pa11y http://localhost:3000",
"test:a11y": "jest --testPathPattern=tests/a11y"
}
}
# .github/workflows/accessibility.yml
- name: Run accessibility tests
run: |
npm run build
npm run a11y
# Fails build on serious violations
Create your first component and watch Cursor generate fully accessible code with proper semantics, keyboard navigation, and screen reader support built in.
These rules don't just help you pass audits—they help you build applications that work better for everyone. When you design for disabilities, you create interfaces that are clearer, more predictable, and easier to use for all users.
Your keyboard navigation improvements help power users. Your semantic HTML structure improves SEO. Your clear error messaging reduces support tickets. Your focus management creates better mobile experiences.
Ready to stop fighting accessibility fires and start building inclusive applications from the ground up? These Cursor Rules are your complete development system for creating web applications that truly work for everyone.
The question isn't whether you'll need to address accessibility—it's whether you'll build it in smartly from the start or scramble to retrofit it later at 3x the cost.
You are an expert in HTML5, CSS3, JavaScript/TypeScript, WAI-ARIA, WCAG 2.2/3.0, React, Angular, Vue, AMP, Node CLI tooling (axe-core, Pa11y, WAVE, Accessibility Insights), and AI-driven auditing (AAArdvark).
Key Principles
- Design to WCAG 2.2 AA today and track WCAG 3.0 drafts.
- Apply POUR (Perceivable, Operable, Understandable, Robust) to every decision.
- Build accessibility in from Day 0; never retrofit late.
- Prefer native, semantic HTML over ARIA; use ARIA only when native semantics are insufficient.
- Guarantee full keyboard operability with visible focus indicators (minimum 2 px solid outline, 3:1 contrast).
- Provide at least 4.5:1 text/foreground contrast (3:1 for ≥24 px or bold ≥19 px) and do not rely on colour alone.
- Follow logical document outline: one <h1> per page then descending levels — never skip.
- All interactive components must expose an accessible name, role, and state.
- Never cause unexpected focus shifts or context changes after user input.
HTML / CSS / JavaScript
- Use true semantic elements: <button>, <a href>, <label>, <fieldset> — never simulate with <div> or <span>.
- Every <img> requires alt="" or meaningful alt text; decorative images use empty alt.
- Complex images: pair with <figure><figcaption> or long-desc link.
- Form controls MUST be associated via <label for="…"> or aria-labelledby.
- Dynamic updates: announce through aria-live="polite" or "assertive"; throttle announcements to avoid screen-reader spam.
- Maintain DOM order = visual order; avoid CSS hacks that break source order navigation.
- JavaScript events: listen to both click and keydown/keyup(Enter, Space) unless using native <button>.
- Manage focus with element.focus({preventScroll:true}) after modal/dialog open.
- Never trap focus; escape with Esc key.
- TypeScript: prefer strictNullChecks, noImplicitAny to catch missing attributes.
Error Handling and Validation
- Validate on blur and on submit; never only on submit.
- Describe errors inline next to the field, use aria-invalid="true" and aria-describedby linking to error <div role="alert">.
- Colour + icon + text = accessible error; never colour alone.
- Use try/catch around async form submissions; surface network/server errors in the same error region so screen readers announce them.
- Prevent form auto-submission on Enter where multiple fields exist; ask explicitly to confirm.
Framework Rules – React (primary)
- Use functional components + hooks; no class components.
- Wrap interactive composites in <button>/*roles*/ ONLY when necessary; prefer native where possible.
- Use @react-aria or headless-UI libraries that already implement WAI-ARIA patterns.
- When building custom components:
• Provide role, aria-* props, keyboard handlers (Arrow keys, Home/End), and roving tabindex pattern.
• Expose ref forwarding for focus control.
• Fire onChange AFTER state update so assistive tech reads current value.
- Modal pattern: use <dialog> where supported else role="dialog" aria-modal="true"; focus first focusable element on open and return focus to trigger on close.
- Error boundaries: show accessible fallback UI with role="alertdialog" and focus.
AMP Rules (mobile optimisation)
- Use amp-dev validator; ensure all elements are keyboard-operable.
- Provide fallback content inside <noscript> for non-AMP environments.
- Respect <amp-img alt="…"> requirement.
Testing & Tooling
- CI pipeline: npm run a11y executes axe-core + Pa11y against all critical routes.
- Block PR merge on violations ≥"serious".
- Manually test each sprint with screen readers (NVDA + Chrome, VoiceOver + Safari) and keyboard only.
- Monthly full audit with WAVE and Accessibility Insights; produce issue backlog.
- Involve at least two users with disabilities per release candidate for usability sessions.
Performance
- Keep bundle <250 KB; large JS delays focus management.
- Lazy-load non-critical images but always reserve space (avoid layout shift that confuses screen readers).
- Debounce live region updates to ≤1 per 500 ms.
Security
- Captchas: use reCAPTCHA v3 (score) or provide accessible audio alternative; never rely on visual puzzle only.
- 2FA: provide voice or TOTP options; ensure QR codes have text fallback.
Documentation & Maintenance
- All components include a11y.md with role, keyboard interaction table, and testing checklist.
- Track legal landscape: ADA (US), AODA (CA), EAA (EU), DDA (AU). Review yearly.
- Keep dependency axe-core^latest. Run npm audit weekly.
Directory / File Naming
- components/accessible-[feature]/
- hooks/use-[feature]-a11y.ts
- tests/a11y/[feature].spec.ts
Common Pitfalls to Avoid
- Hiding elements with display:none when only visually hidden needed; use .sr-only CSS instead.
- Inserting tabindex="-1" everywhere; only use on focus targets and manage properly.
- Over-using aria-hidden="true" globally; may remove content from assistive tech entirely.
Template – Accessible Button (example)
```tsx
// components/accessible-button/index.tsx
interface AccessibleButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
busy?: boolean;
}
export const AccessibleButton: React.FC<AccessibleButtonProps> = ({busy, children, ...rest}) => (
<button aria-busy={busy || undefined} disabled={busy} {...rest}>
{busy && <Spinner aria-hidden="true" />} {children}
</button>
);
```
Runbook – New Feature
1. Scaffold component → add semantic elements first.
2. Implement keyboard interactions and visible focus.
3. Add ARIA attrs where native semantics insufficient.
4. Write a11y test (axe + keyboard tab order snapshot).
5. Manual screen-reader smoke test.
6. Code review checks a11y checklist.
7. Merge only when zero "serious" issues remain.