Skip to content

Anti patterns and Protocol

fecarrico edited this page Jul 25, 2026 · 3 revisions

Anti-patterns and The Complex 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.

The Ultimate Sin: The Clickable Div

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>

Leaked Focus Traps

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:

  1. Focus MUST move into the modal.
  2. Focus MUST be trapped within the modal.
  3. Focus MUST return to the triggering element when the modal is closed.

ARIA Soup

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.2

The 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.

Placeholder Labels

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).


The Complex Component Protocol

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:

  1. Identify: The AI must first search the official WAI-ARIA APG to see if a similar pattern exists.
  2. 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.
  3. 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.
  4. 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.

Clone this wiki locally