CodeCraftingHub
Home

Editor

Write, edit & format code with syntax highlighting

Sandbox

Run & test code in isolated environments

About UsToolsBlogs
Log in

CodeCraftingHub

Build, validate, and analyze code in one place with an engineering-first workflow.

Core

  • Workspace
  • Complexity analysis
  • Code tools (roadmap)

Elsewhere

  • GitHub
  • LinkedIn
  • Blogs

Site

About

© 2026 CodeCrafting. Execution + AI conversion modules are on the roadmap.

HomeAboutToolsEditorSandboxBlogsLog in
CodeCraftingHub
Home

Editor

Write, edit & format code with syntax highlighting

Sandbox

Run & test code in isolated environments

About UsToolsBlogs
Log in

CodeCraftingHub

Build, validate, and analyze code in one place with an engineering-first workflow.

Core

  • Workspace
  • Complexity analysis
  • Code tools (roadmap)

Elsewhere

  • GitHub
  • LinkedIn
  • Blogs

Site

About

© 2026 CodeCrafting. Execution + AI conversion modules are on the roadmap.

HomeAboutToolsEditorSandboxBlogsLog in
CodeCraftingHub
Home

Editor

Write, edit & format code with syntax highlighting

Sandbox

Run & test code in isolated environments

About UsToolsBlogs
Log in
accessibility
Back to Articles

CodeCraftinghub

Front End

The Accessibility Habit That Takes 30 Seconds and Saves You a Lawsuit

By Usman AliApril 29, 202612 min read

The European Accessibility Act now enforces WCAG 2.1 AA with fines up to €100k. These aren't edge cases. You can catch them in thirty seconds.

Most developers think an accessibility lawsuit comes from some complicated screen‑reader failure they'd never find on their own. But the lawsuits tell a different story. In 2025, plaintiffs filed 3,117 website accessibility lawsuits in U.S. federal court up 27% from the year before. And when you include state courts, that figure jumps past 5,000 cases. The vast majority cite basic keyboard failures: unreachable buttons, missing focus indicators, modal traps. Across the Atlantic, the European Accessibility Act became enforceable on June 28, 2025, with penalties that can reach €100,000 or more per violation, depending on the member state and severity. These aren't exotic bugs. They're things you can catch yourself in half a minute, with your mouse unplugged.

The 30-Second Habit That Catches More Bugs Than Your Entire QA Pipeline

I used to believe accessibility testing required a screen reader, a WCAG certification, and at least an afternoon I didn't have. Then a friend who uses only a keyboard to navigate the web watched me demo a new feature.

Within 45 seconds, he said, "I'm stuck. I can't get out of your modal."

I had tested that modal twenty times. With a mouse. It worked perfectly.

That moment reframed everything for me. I started running a single check before every PR unplug the mouse, put it behind the monitor, and navigate the entire feature using only the keyboard. It takes 30 seconds. And I'll say this without exaggeration: this habit has caught more real usability failures than any other single practice in my workflow.

Let me show you exactly what I do, why it matters, and how it connects to something bigger than just "being a good developer."

The State of Things: Why This Matters More Than You Think

Before I get into the technique, let's talk numbers because the landscape has shifted in ways most developers haven't noticed.

In 2025, plaintiffs filed 3,117 website accessibility lawsuits in US federal court a 27% increase from 2024. If you include state court filings, that number jumps to over 5,100 cases. E-commerce sites are hit hardest: depending on the dataset, 70% to 77% of these lawsuits target online retailers. Among the top 500 e-commerce sites, more than one in three received at least one ADA lawsuit.

Across the Atlantic, the European Accessibility Act (EAA) came into force on June 28, 2025, requiring websites and mobile apps serving EU customers to meet WCAG 2.1 AA standards. Penalties reach up to €100,000 or 4-5% of annual turnover for serious violations. Enforcement is no longer theoretical it's accelerating.

Here's the thing most developers miss: these lawsuits and penalties aren't driven by exotic, hard to find accessibility failures. They're built on the basics. Keyboard accessibility. Focus visibility. Logical tab order. The stuff you can test in half a minute.

A single keyboard trap where focus enters a component but can't leave using standard keyboard commands is a direct violation of WCAG 2.1.2 (Level A). Missing focus indicators violate WCAG 2.4.7 (Level AA). These two failures alone are among the most commonly cited in demand letters because they're trivially easy for a plaintiff's lawyer to document: open the site, unplug the mouse, press Tab repeatedly, and record the screen.

The Habit: A 30-Second Keyboard Walkthrough

Here's the ritual. It requires no tools, no extensions, no setup. Just your keyboard.

Step 1: Unplug the mouse. I'm not being dramatic. Physically put it behind your monitor. The temptation to reach for it is real, and if you keep it within reach, you'll cheat.

Step 2: Reload the page. Start from a clean state. Focus should land on the first interactive element usually a skip to content link or the first link in the navigation.

Step 3: Navigate the entire feature using Tab. Press Tab to move forward, Shift+Tab to move backward. Try to complete the primary user task: fill out that form, submit that order, open and close that modal.

Step 4: Use Enter and Space to activate. Buttons respond to both. Links respond to Enter. If your custom dropdown opens with a mouse click but ignores the keyboard entirely, you'll know immediately.

Step 5: Use Escape to close. Modals, dropdowns, autocomplete panels Esc should dismiss them and return focus to where it was before they opened.

Step 6: Use Arrow keys where applicable. Tab panels, radio groups, sliders, and menu bars often need Arrow key navigation. If you built a custom carousel as a collection of divs with click handlers, arrow keys won't work and that's a violation of WCAG 2.1.1.

That's it. Thirty seconds. I run this on every component I build or review, right before opening the PR. It's so fast that skipping it is never justified.

What You'll Find: The Usual Suspects

If you start doing this consistently, you'll start noticing the same failures over and over across your own code, your teammates' code, and especially AI-generated code. Here are the patterns I see most often:

1. The Disappearing Focus Indicator

You're tabbing through a page and suddenly you have no idea where you are. An outline flashes somewhere? Maybe?

This happens because somewhere in your CSS or more likely, in a CSS reset you copied years ago someone wrote:

css
*:focus {
  outline: none;
}

This single line violates WCAG 2.4.7 (Focus Visible) and is arguably the most common accessibility failure in production. It's everywhere. Developers remove the default focus outline because they think it's ugly, then forget to replace it with something else.

The fix takes one minute:

css
/* Remove the offending line, then add: */
:focus-visible {
  outline: 2px solid #4A90D9;
  outline-offset: 2px;
}

:focus-visible is the crucial piece. It shows the outline when navigating by keyboard but not when clicking with a mouse the best of both worlds. This alone will fix more accessibility failures than any overlay widget ever will. In fact, accessibility overlays those JavaScript widgets promising one-click WCAG compliance cannot fix keyboard navigation issues at all, because those require actual source-code modifications.

2. The Modal That Won't Let Go

You open a modal. You close it by clicking the backdrop. Looks fine.

But try this: open the modal, then press Tab. Keep pressing Tab. Does focus eventually escape back to the underlying page while the modal is still open? That's a violation. Does focus cycle endlessly inside the modal with no way to dismiss it via keyboard? That's a keyboard trap, violating WCAG 2.1.2.

Both are equally bad.

A proper modal needs at minimum:

Focus moves to the first focusable element when it opens.

Focus is trapped inside while the modal is open (Tab wraps from last element back to first, Shift+Tab wraps from first back to last).

Escape closes the modal and returns focus to the element that triggered it.

I'm not going to write a focus-trap implementation here because you should almost certainly use a library rather than rolling your own. But here's the configuration pattern that matters:

javascript
// Using a focus-trap library:
<FocusTrap
  active={isModalOpen}
  onDeactivate={() => {
    setIsModalOpen(false);
    triggerRef.current?.focus(); // Return focus to trigger
  }}
>
  <div role="dialog" aria-modal="true" aria-labelledby="modal-title">
    <h2 id="modal-title">Confirm Deletion</h2>
    <button onClick={handleClose}>Cancel</button>
    <button onClick={handleConfirm}>Delete</button>
  </div>
</FocusTrap>

If your modal doesn't close on Escape, add this:

javascript
useEffect(() => {
  const handleKeyDown = (e) => {
    if (e.key === 'Escape' && isModalOpen) {
      setIsModalOpen(false);
    }
  };
  window.addEventListener('keydown', handleKeyDown);
  return () => window.removeEventListener('keydown', handleKeyDown);
}, [isModalOpen]);

These aren't advanced techniques. They're table stakes. And my 30-second check catches them every time.

3. The Unreachable Click Handler

This one is everywhere in modern React codebases. A designer wants a clickable card. The developer writes:

javascript
<div className="card" onClick={() => navigate(`/product/${id}`)}>
  <img src={image} alt={title} />
  <h3>{title}</h3>
  <p>{price}</p>
</div>

Looks clean. Feels modern. And it's completely invisible to keyboard users.

A div with an onClick is not a button. It doesn't receive focus. It doesn't respond to Enter or Space. A screen reader won't announce it as interactive. You've just built a feature that excludes anyone who can't use a mouse.

The fix is either to use a semantic element or to make the div properly interactive:

javascript
// Option A: Use a button (preferred if the card is a primary action):
<button
  className="card"
  onClick={() => navigate(`/product/${id}`)}
  aria-label={`View ${title}`}
>
  <img src={image} alt="" /> {/* decorative when button has aria-label */}
  <h3>{title}</h3>
  <p>{price}</p>
</button>

// Option B: Make the div accessible (if it contains nested interactive elements):
<div
  className="card"
  role="button"
  tabIndex={0}
  onClick={() => navigate(`/product/${id}`)}
  onKeyDown={(e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      navigate(`/product/${id}`);
    }
  }}
>
  {/* content */}
</div>

Option A is almost always better. Native HTML elements come with keyboard interaction built in. WCAG explicitly recommends using native elements over custom scripted controls buttons, links, and form elements generally avoid keyboard input pitfalls entirely.

4. The Illogical Tab Order

You're tabbing through a form. The fields go: Name → Email → City → Street Address. That makes no sense visually or logically. Street Address should come after Name, before City.

This happens when developers use tabindex with positive values to manually control order:

html
<input type="text" placeholder="Name" tabindex="1" />
<input type="text" placeholder="Email" tabindex="3" />
<input type="text" placeholder="City" tabindex="4" />
<input type="text" placeholder="Street Address" tabindex="2" />

Positive tabindex values override the natural DOM order and are notoriously difficult to manage. They're also almost never necessary. The following will be all over your code:

html
<!-- Just don't set tabindex at all. DOM order handles it: -->
<input type="text" placeholder="Name" />
<input type="text" placeholder="Street Address" />
<input type="text" placeholder="City" />
<input type="text" placeholder="Email" />

The fix is usually deleting the tabindex attributes entirely. If the visual order doesn't match the DOM order, the DOM order is what needs to change not the tabindex.

The AI Dimension: Why Generated Code Makes This Worse

I've written before about how AI coding assistants tend to ignore security and accessibility constraints unless you explicitly enforce them. Keyboard accessibility is a perfect case study.

When Cursor or Copilot generates a component, it optimizes for "looks right" and "passes the smoke test." It does not optimize for "navigable by keyboard." I've seen AI generate:

  • Clickable div elements with no keyboard handlers at all.
  • Modals using display: none (which removes them from the DOM) instead of visibility: hidden or proper focus management.
  • Custom dropdowns built from div elements with an onClick and zero ARIA attributes.
  • Focus styles aggressively removed in the generated index.css because outline: none appears in so many training examples.

None of this is the AI's fault. It's predicting the most statistically probable code, and the most statistically probable code on the internet has terrible accessibility. This means your review process is now your accessibility defense. The 30-second keyboard walkthrough is the fastest, cheapest scan you can run on every generated block before it reaches a branch.

Overlay tools won't save you here either. AccessiBe, UserWay, EqualWeb these JavaScript widgets claim to fix accessibility automatically, but they literally cannot fix structural issues like missing keyboard handlers, broken focus order, or improper semantic HTML. Those require source-level changes. Worse, sites using overlays are increasingly named in lawsuits, because plaintiffs' lawyers have learned that overlays don't provide meaningful accessibility. The only real defense is building it correctly in the first place.

A Real Walkthrough: The Checkout Form

Let me walk you through a real example from a project I worked on. A standard e-commerce checkout form: shipping details, payment method, review order, place order.

I ran my 30-second keyboard check. Here's what I found:

First tab: The "Skip to main content" link appeared good. Fashion, but functional.

Second tab: Focus landed on the first form field, "Full Name." Expected.

Tabs 3-5: Email, Phone, Address all in logical order. So far so good.

Tab 6: Focus disappeared entirely. I couldn't see where I was.

This was the promo code field. The designer had styled it to look like a clean text link ("+ Add Promo Code"), but the developer had implemented it as a span with an onClick handler. Zero keyboard accessibility. A visually impaired user tabbing through the form would hit an invisible wall.

Fix: Changed it to a <button> element with a visible focus style. Two lines of code.

Tab 7: Focus entered the payment section. The "Credit Card" and "PayPal" options appeared as visually distinct tabs, but the keyboard couldn't switch between them. Arrow keys did nothing.

Fix: Added role="tablist" and role="tab" with basic Arrow key handlers. Fifteen lines of code. Fixed.

Tabs 8-10: Focus moved through the credit card fields in the expected order.

Tab 11: "Place Order" button. Focus was visible. Enter activated it. Works.

Total time: 45 seconds. Two failures found. Both would have been cited in an ADA demand letter. Total fix time: under five minutes.

Why This Connects to the Law (Without the Fear-Mongering)

I don't want to lead with legal threats because that's not why we build accessible software. We build it because our job is to make things that work for people all people, including the 15% to 20% of the global population with some form of disability. That's the fundamental principle.

But I'd be lying if I said the legal landscape didn't matter. And it's shifting in ways that directly reward habits like the keyboard walkthrough.

The failures my 30-second check catches map directly to WCAG success criteria that appear in a huge percentage of lawsuits:

What I FindCan't reach a button with keyboardFocus trapped in modalFocus order is illogicalFocus indicator missingCustom control ignores arrow keys
WCAG Criterion2.1.1 Keyboard2.1.2 No Keyboard Trap2.4.3 Focus Order2.4.7 Focus Visible2.1.1 Keyboard
LevelAA

These five criteria are among the easiest to test and the most frequently violated. A single 30-second walkthrough catches four of them. That's not nothing especially when the EAA is now actively enforced and US federal cases are up 27% year over year.

The lawsuits aren't hypothetical. In a 2025 case against an e-commerce site, the plaintiff's complaint specifically cited "inadequate navigation tools" as a barrier preventing blind users from making purchases. In another case, a visually-impaired plaintiff brought claims for "numerous accessibility barriers" that prevented them from navigating promotional content. These failures are keyboard-level issues. They're not about screen reader nuance. They're about basic operability.

And here's the part that actually matters: the same things that expose you to legal risk are the things that make your product worse for everyone. Keyboard accessibility isn't just for blind users. It's for people with motor impairments who can't use a mouse. It's for power users who prefer keyboard shortcuts for speed. It's for someone with a broken trackpad. Fixing these issues makes your product better for all of them.


Building the Habit: A Practical Setup

The hardest part of any habit is remembering to do it. Here's how I made this stick:

In your PR template. Add a checkbox: [ ] Keyboard navigation tested (Tab, Enter, Esc, Arrow keys on all interactive elements). It takes zero additional time and serves as a social forcing function nobody wants to be the person who unchecked it.

In your definition of done. If a feature doesn't support keyboard navigation, it's not done. Period. Ship it behind a feature flag if you must, but don't merge it into main without keyboard support. This is the single most effective policy I've seen for shifting team culture around accessibility.

Ignore "perfect" WCAG compliance at first. You don't need to memorize all 78 success criteria. Start with the four that the keyboard walkthrough catches: 2.1.1 (Keyboard), 2.1.2 (No Keyboard Trap), 2.4.3 (Focus Order), and 2.4.7 (Focus Visible). These are all Level A or AA and cover the overwhelming majority of real-world barriers. Get these right, and you're meaningfully accessible. Chase perfection later.

Test with real assistive technology when you can. Once the keyboard check is muscle memory, the next step is testing with an actual screen reader VoiceOver on Mac, NVDA on Windows, or even just firing up a browser extension. You'll catch things the keyboard check misses: missing labels, unannounced state changes, improper heading hierarchy.

Short Checklist: The 30-Second Keyboard Audit

Here's the stripped-down version. Print it, bookmark it, stick it on the monitor behind the unplugged mouse:

  • Tab through every interactive element. Does focus reach everything clickable? Can you return with Shift+Tab?
  • Focus indicator always visible. Can you see where you are at every step? If not, fix :focus-visible.
  • No traps. Can you leave every modal, dropdown, and autocomplete panel using only Tab or Escape?
  • Logical tab order. Does focus move in a sequence that matches the visual layout? If not, fix your DOM order don't use positive tabindex.
  • Enter and Space activate. Buttons respond to both. Links to Enter. Custom controls behave like their native counterparts.
  • Arrow keys work where expected. Radio groups, tab panels, sliders, and menus should respond to arrow keys.
  • Escape dismisses. Modals, popups, and overlays close and return focus to the trigger.

This habit changed how I build software. It takes less time than checking Slack, it catches failures that automated tools miss, and it makes me better at the part of my job that actually matters: building things people can use.

Try it on your next PR. I bet you find something.

  • The 30-Second Habit That Catches More Bugs Than Your Entire QA Pipeline
  • The State of Things: Why This Matters More Than You Think
  • The Habit: A 30-Second Keyboard Walkthrough

Comments

No approved comments yet.

Related Articles

How to Use Chrome DevTools MCP Server with Cursor IDE
Front End

How to Use Chrome DevTools MCP Server with Cursor IDE

If you’ve tried to connect the Chrome DevTools MCP server to Cursor IDE, you might have run into a frustrating wall

Coding
Front End

React vs. Next.js: Navigating the Architectural Shift in Modern Front-End Development

The Architect’s Dilemma: Is Next.js Consuming React, or Saving It? Let’s be real for a second: the "React vs. Next.js" debate is exhausting. If you spend five minutes on tech social media, you’ll see developers acting like choosing one over the other is a moral failing. But here’s the truth I’ve learned after breaking a few dozen production apps: It’s not about. which tool is better. It’s about how much "magic" you’re willing to trade for control. In 2026, as AI starts handling the "simple" code generation, our value as engineers isn't just in writing syntax—it’s in technical judgment. It’s knowing where your code should live and how it should reach the user. 1. The "Pure React" Purist: Power in Control When you opt for a library like React (likely paired with a lightning-fast bundler like Vite), you are choosing transparency. There is no "magic" file-based routing. There is no hidden middleware. It is just you, your components, and the browser’s DOM. For those of us who grew up debugging complex re-renders and mastering the useMemo hook, this level of control is addictive. Where it shines Complex Client-Side Tools: Think dashboards with 10k+ data points where rendering performance is more important than SEO. Internal Applications: When you don't need to be indexed by Google and want to keep your bundle size strictly under your own thumb. Total Architectural Freedom: React is the ultimate Lego set. It doesn't try to be your boss. It’s perfect for engineers who want to build their own systems from the ground up. 2. The Next.js Paradigm: Performance by Default Then we have Next.js. It’s no longer just a "React wrapper"; it is a comprehensive web framework that has fundamentally changed the "vibe" of the frontend. With the advent of the App Router and Server Components, Next.js addresses the biggest headache of modern SPAs: The Hydration Gap. Instead of making the user wait for a massive JavaScript bundle to download before they see anything, Next.js sends pre-rendered HTML. It’s that instant gratification—that "snap"—that makes a site feel premium. It handles the "boring" stuff (Image optimization, Font loading, SEO) so you can focus on building features. The "Cage" of Convenience: The trade-off? You have to do things the "Next way." If you want to use their Middleware or caching strategies, you have to play by their rules. For some, this is a relief. For others, it feels like a cage. 3. The Technical Breakdown How do they actually stack up when the pressure is on? 4. The Human Verdict: Which One Should You Pick? I’ve seen plenty of projects fail because they chose a stack based on a trend rather than a requirement. Choose Next.js if: You are building anything that needs to be "discovered." If your business depends on a search engine—like an e-commerce platform, a public SaaS, or a content site—Next.js is the only logical choice. The SEO and performance wins out of the box are too valuable to ignore. Choose Pure React if: You are building an internal tool, a heavy-duty editor (like a Figma-style canvas), or a localized app where SEO is irrelevant. Go this route if you want to sharpen your architectural skills and have 100% control over the execution pipeline. Final Thoughts: Don't Get Analysis Paralysis At the end of the day, your users don't care if you used a Server Component or a useEffect hook. They care if the app works, if it's fast, and if it solves their problem. Pick the tool that makes you feel productive, not just the one that’s trending. Both React and Next.js are incredible feats of engineering. Your job is to be the architect who knows which tool to pull from the belt. What’s your go-to for your next project? Let’s talk about it in the comments.

Want More Engineering Deep Dives?

Join the newsletter for practical insights on architecture, code quality, and developer workflow.

CodeCraftingHub

Build, validate, and analyze code in one place with an engineering-first workflow.

Core

  • Workspace
  • Complexity analysis
  • Code tools (roadmap)

Elsewhere

  • GitHub
  • LinkedIn
  • Blogs

Site

About

© 2026 CodeCrafting. Execution + AI conversion modules are on the roadmap.

HomeAboutToolsEditorSandboxBlogsLog in
A
AA
A
Real-World ConsequenceCore functionality unavailableUser literally cannot continueConfusing, disorienting experienceUser doesn't know where they arePattern violates user expectations
What You'll Find: The Usual Suspects
  • 1. The Disappearing Focus Indicator
  • 2. The Modal That Won't Let Go
  • 3. The Unreachable Click Handler
  • 4. The Illogical Tab Order
  • The AI Dimension: Why Generated Code Makes This Worse
  • A Real Walkthrough: The Checkout Form
  • Why This Connects to the Law (Without the Fear-Mongering)
  • Short Checklist: The 30-Second Keyboard Audit