DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Why Your Test Automation Is Always Behind the Code And the Architecture That Fixes It
  • A General Overview of TCPCopy Architecture
  • Cypress vs. Selenium: Choosing the Best Tool for Your Automation Needs
  • Developers Are Scaling Faster Than Ever: Here’s How Security Can Keep Up

Trending

  • The Agentic Agile Office: Streamlining Enterprise Agile With Autonomous AI Agents
  • Stateless JWT Auth Microservice Architecture With Spring Boot 3 and Redis Sentinel
  • 8 RAG Patterns You Should Stop Ignoring
  • A Hands-On ABAP RESTful Programming Model Guide
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. More Than Just Buttons: A Frontend Engineer's Exploration of Accessibility Frameworks

More Than Just Buttons: A Frontend Engineer's Exploration of Accessibility Frameworks

Architect Accessibility from Day 0, focus/live-region utilities, keyboard-friendly components, axe-core CI tests, and a "mouse-free" review culture.

By 
Mohit Menghnani user avatar
Mohit Menghnani
DZone Core CORE ·
Jul. 22, 25 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
1.6K Views

Join the DZone community and get the full member experience.

Join For Free

Accessibility is often treated as actions that have to be implemented like checkboxes. In this scenario, contrast, alt images, and tagging will create structure. However, in real-world scenarios that involve advanced frontend systems, accessible interfaces are products of architectural decisions.

In a practical scenario, as a senior engineer, there are multiple factors of influence apart from the coding aspects. The impact radiates to the workflows of development, component systems, and patterns, which are used or created by others. If there is no strategy incorporated during construction for accessibility, there will be difficulties or bridge gaps that need to be crossed when trying to patch this problem later on, causing multiple regressions.

In this article, I present a solution that deals with practical coding and focuses on efficiency of use with accessibility on the frontend architecture to go beyond minimal requirements, to create and enhance interaction with inclusivity.

1. Ease of Access Focus On Custom Components to Ensure All Users Have Equal Access

Final designs of components play a crucial role and may be the first step to ensuring access for all users. Custom dropdowns like the ones described for modals, tooltips and other like widgets require to be sculpted in a manner where behavior which is considered accessible is put into the design structure, which requires far more than just adding attributes of ARIA tags.

Example: Dropdown With Keyboard Usability and ARIA Role

JSX
 
import { useState, useRef } from "react";

export function AccessibleDropdown({ label, options }: { label: string; options: string[] }) {
  const [isOpen, setIsOpen] = useState(false);
  const [highlighted, setHighlighted] = useState<number | null>(null);
  const buttonRef = useRef<HTMLButtonElement>(null);

  return (
    <div>
      <button
        aria-haspopup="listbox"
        aria-expanded={isOpen}
        ref={buttonRef}
        onClick={() => setIsOpen(!isOpen)}
        onKeyDown={(e) => {
          if (e.key === "ArrowDown") {
            setIsOpen(true);
            setHighlighted(0);
          }
        }}
      >
        {label}
      </button>
      {isOpen && (
        <ul role="listbox" aria-activedescendant={`option-${highlighted}`}>
          {options.map((option, idx) => (
            <li
              key={option}
              id={`option-${idx}`}
              role="option"
              aria-selected={highlighted === idx}
              tabIndex={-1}
              onMouseEnter={() => setHighlighted(idx)}
              onClick={() => {
                setIsOpen(false);
                buttonRef.current?.focus();
              }}
            >
              {option}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}


Benefits:

  • Keyboard navigation: It supports ArrowDown and restores focus.
  • Screen reader compatible: It makes uses of roles, aria-haspopup as well as aria-selected.
  • Reusable: Encapsulates logic so product engineers don’t need to reimplement accessibility behavior each time.

2. Management of Focus, Announcements and Dynamic Content

Accessibility is often lost with dynamic content such as modals, toasts, or tabbed interfaces whenever focus is not handled appropriately. Both screen readers and users who rely on keyboards have to navigate through a set context and order.

Example: Introducing Status Announcements With Live Region Hooks

JSX
 
import { useEffect, useState } from "react";

export function useLiveRegion() {
  const [message, setMessage] = useState("");

  useEffect(() => {
    if (message) {
      const timeout = setTimeout(() => setMessage(""), 1000);
      return () => clearTimeout(timeout);
    }
  }, [message]);

  return {
    announce: (text: string) => setMessage(text),
    region: (
      <div
        role="status"
        aria-live="polite"
        style={{ position: "absolute", left: "-9999px", height: 0, overflow: "hidden" }}
      >
        {message}
      </div>
    ),
  };
}

Usage:

JSX
 
const { announce, region } = useLiveRegion();

useEffect(() => {
  if (formSubmitted) announce("Form submitted successfully.");
}, [formSubmitted]);

return (
  <>
    {region}
    {/* rest of your UI */}
  </>
);

Benefits:

  • Non-intrusive: Does not detract attention from users who can see.
  • Effectively: Delivers important notifications to the users of reading aids.
  • Reusable: Wraps best practices into a clean hook thus no need to redeployed all over again.

3. Testing And Capturing Accessibility Regressions At Scale

Accessibility regressions creep in without manual auditing.

Example: CI friendly A11y Testing Using Playwright and Axe-Core

JSX
 
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';

test('Homepage should have no accessibility violations', async ({ page }) => {
  await page.goto('http://localhost:3000');

  const results = await new AxeBuilder({ page }).analyze();
  expect(results.violations).toEqual([]);
});

Benefits:

  • Integration with CI: solves the problem of merging new issues.
  • Scalable: works across pages and flows.
  • Immediate feedback: provides developers with the learning process as they code.

4. Real-World Example: Keyboard Navigation Regression

We had a handover and implemented a form with several panels in one of the production systems. The testing passed it, but screen reader users were completely stuck not being able to reach the “Next” button as focus was stuck in a closed accordion.

Fix: Focus Trap Utility

JavaScript
 
export function trapFocus(container: HTMLElement) {
  const focusable = container.querySelectorAll<HTMLElement>(
    'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
  );
  const first = focusable[0];
  const last = focusable[focusable.length - 1];

  container.addEventListener("keydown", (e) => {
    if (e.key === "Tab") {
      if (e.shiftKey && document.activeElement === first) {
        e.preventDefault();
        last.focus();
      } else if (!e.shiftKey && document.activeElement === last) {
        e.preventDefault();
        first.focus();
      }
    }
  });
}

 Benefits:

  • Avoids broken tab order.
  • Enhances modal and wizard UX.
  • Encapsulated logic: Easier to test and refactor.

5. Cultivating Inclusive Engineering Culture

Architecture generates leverage but culture maintains it. As emblematic engineers, we have the ability to make accessible, employable universally by:

  • Conducting accessibility focused design reviews
  • Encouraging “Can this be operated without a mouse?” to be used
  • Designing reusable building blocks that assume non-strict conditions and edge cases.
  • Taping screener presentations for PMs and designers
  • Trained in tracking the accessibility of disabling features as regressions

Embedding the conversation around code reframes accessibility to “not extra work, part of the process.”

Conclusion

Accessibility isn’t about checking a box and closing off a list. It's a way of thinking that stretches across elements, designs and teams. As engineers who care about quality and inclusion, we are equipped — and accountable for building ways for systems to inclusively work for everyone.

Consider this the next time you are designing a component or checking a pull request: instead of simply asking, “Does it perform its function?” try asking, “Can all of my users interact with this, even the ones that I will never meet?”

Architecture Testing Web accessibility

Opinions expressed by DZone contributors are their own.

Related

  • Why Your Test Automation Is Always Behind the Code And the Architecture That Fixes It
  • A General Overview of TCPCopy Architecture
  • Cypress vs. Selenium: Choosing the Best Tool for Your Automation Needs
  • Developers Are Scaling Faster Than Ever: Here’s How Security Can Keep Up

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook