-
Notifications
You must be signed in to change notification settings - Fork 13
Anti patterns and Protocol
When dealing with AI-generated code, knowing what not to do is often more important than knowing what to do.
A11Y.md explicitly bans certain development patterns. If you or your AI agent attempt to use them, you are violating the core architecture of the project.
This is the most prevalent anti-pattern in modern frontend development, massively accelerated by AI agents optimizing for visual aesthetics.
The Violation: Adding an onClick event to a non-semantic element like a <div> or a <span>.
// ❌ CRITICAL VIOLATION
<div className="beautiful-button" onClick={() => submit()}>
Submit
</div>Why it fails: A <div> is invisible to a keyboard. A user navigating with Tab will pass right over it. A screen reader will not announce it as actionable. The feature is completely broken for assistive tech.
The Solution: The AI is instructed (via Rule 6 of the Behavioral Contract) to intercept this and replace it with a native <button>. If a <div> must be used for legacy reasons, the AI is forced to implement the entire ARIA pattern:
// ✅ Acceptable Fallback (But native is preferred)
<div
role="button"
tabIndex={0}
onClick={() => submit()}
onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') submit() }}
>
Submit
</div>When a modal or dialogue opens, the keyboard focus must be trapped inside it.
The Violation: A modal opens, but the user can press Tab and navigate to the links on the background page (which might be obscured by a dark overlay).
The Solution: When a modal opens:
- Focus MUST move into the modal.
- Focus MUST be trapped within the modal.
- Focus MUST return to the triggering element when the modal is closed.
Div soup had a sequel. The WebAIM Million 2026 found pages now averaging 133+ ARIA attributes — more than 6× the 2019 figure — and pages with more ARIA showing more detected errors, not fewer. Frameworks and AI agents generate ARIA confidently; most of it is noise or actively harmful.
The Violation: Adding ARIA where native HTML already provides the semantics.
// ❌ VIOLATIONS — ARIA as seasoning
<button role="button">Save</button> // redundant role — valid per ARIA in HTML, but NOT RECOMMENDED
<button aria-label="Save">Save</button> // duplicates visible text — invites drift into an SC 2.5.3 failure
<button aria-expanded="false" onClick={toggle}>Menu</button> // hardcoded state, never synced — fails SC 4.1.2The Rule: No ARIA is better than bad ARIA. ARIA is the fallback for gaps in native semantics (per the W3C's First Rule of ARIA Use) — the agent must reach for the native element first, and justify every ARIA attribute it adds.
The Violation: Using the placeholder attribute as the only label for an input field.
// ❌ HIGH VIOLATION
<input type="text" placeholder="Enter your email" />Why it fails: Placeholders disappear the moment the user starts typing. This causes cognitive friction, and many screen readers ignore placeholders entirely.
The Solution: Always use explicit <label> tags tied to the input via id and for (or htmlFor).
What happens when you need to build a highly exotic component (like a multi-axis data visualization chart) that isn't covered by the 21 reference guides?
The AI is explicitly forbidden from "guessing" or hallucinating a solution. It must follow a strict 4-step protocol:
- Identify: The AI must first search the official WAI-ARIA APG to see if a similar pattern exists.
- Validate: The AI must request human validation with a screen reader. It is explicitly forbidden from claiming this test was performed, or from fabricating its results — screen reader testing is perceptual and cannot be simulated by the model.
- Document: If no exact pattern exists, the AI must explicitly document the expected keyboard behavior and screen reader announcements to align with the human developer.
-
Scale: Once the human validates the exotic component, the AI records the resolved pattern in
A11Y-DECISIONS.md— indexed by pattern — so future components reuse it instead of re-deriving it.
Project A11Y.md | The Persistent Context System for Accessibility Created by Felipe A. Carriço | MIT License
♿ Accessibility is not a feature; it's a precondition for use.