F79: When Focus Disappears from the Accessibility API

Patricia
digitalwcagscreen readerscustom componentsariatitle ii

Patricia · AI Research Engine

Analytical lens: Risk/Legal Priority

Government compliance, Title II, case law

AI-assisted · Source-linked · Editorially reviewed · Methodology

Trust note

This article was drafted with AI assistance, reviewed against accessibility.chat editorial standards, and should be treated as research and education rather than legal advice. We prioritize primary sources and correct material errors.

A caregiver helps a visually impaired man read a Braille book in a library setting.
Photo by Mikhail Nilov on Pexels

There is no focus notification. The menu is interactive. The keyboard works, visually. But when a screen reader user navigates into the custom menu, the assistive technology receives no signal about which item is currently selected. Focus exists in the visual layer. It does not exist in the accessibility layer.

This is WCAG 2.2 Failure F79 (opens in new window). It's been in the W3C catalog long enough that its continued prevalence in production code is, frankly, exhausting.

The Failure

F79 documents a specific, recurring pattern: a custom user interface component — typically a menu, listbox, tab panel, or similar widget — is built with scripted mouse and keyboard event handling, but the developer never exposes focus state through the platform's accessibility API. The component looks interactive. It behaves interactively. Screen magnification users may even see a visible highlight move as they navigate. But assistive technology receives no programmatic notification that focus has moved.

The W3C's description is precise: "assistive technology can only determine that focus is somewhere within the menu and cannot determine which menu item has focus."

This is a failure of Success Criterion 4.1.2 Name, Role, Value (opens in new window). That criterion requires that for all user interface components, the name, role, and current state — including focus state — can be programmatically determined. Focus state is not optional metadata. It is, as the W3C document notes, "a particularly important facet" of component state.

Why This Matters

Screen readers don't guess where focus is. They listen to the accessibility API. When a user presses the down arrow key to move through a menu, the screen reader expects the API to fire a focus event on the newly selected item. That event triggers the screen reader to announce the item's label, its position in the list, whether it's expanded or collapsed, whether it's checked. Without that event, nothing happens. The user hears silence, or worse, hears the last thing that was announced — which is now wrong.

The disorientation this causes is not minor. A screen reader user attempting to navigate a menu with broken focus notifications is effectively navigating blind within an interface that appears to be working. They may activate the wrong item. They may abandon the task. They may assume the site is broken and leave.

Keyboard-only users who don't use screen readers are partially affected too — if the visual focus indicator is also suppressed (a common companion failure), they have no way to determine their position in the component. But the accessibility API failure in F79 is specifically about the programmatic layer, which means screen reader and switch access users bear the full impact.

This failure applies to all technologies. There is no platform exemption. Web, native app, hybrid — if you build a custom interactive component, you own the accessibility API integration.

The Fix

The source material describes the failure pattern in terms of a custom menu. Here's what the broken pattern looks like conceptually:

HTML
<!-- Broken: Custom menu with no ARIA roles or focus management -->
<div id="menu" class="custom-menu">
<div class="menu-item" onclick="selectItem(this)">Option 1</div>
<div class="menu-item" onclick="selectItem(this)">Option 2</div>
<div class="menu-item" onclick="selectItem(this)">Option 3</div>
</div>

The JavaScript may highlight .menu-item elements on keydown. It may even move a visual cursor. But <div> elements have no implicit ARIA role, no focus semantics, and fire no accessibility events when programmatically highlighted.

The corrected pattern uses the ARIA Authoring Practices Guide menu button pattern (opens in new window) and exposes role, state, and focus properly:

HTML
<!-- Correct: ARIA roles, keyboard focus, and programmatic state -->
<ul role="menu" aria-label="Options">
<li role="menuitem" tabindex="-1">Option 1</li>
<li role="menuitem" tabindex="-1">Option 2</li>
<li role="menuitem" tabindex="-1">Option 3</li>
</ul>
JAVASCRIPT
// Correct: Move actual DOM focus, not just a visual class
function moveFocus(item) {
item.focus(); // This fires the native focus event → accessibility API notified
}

The critical distinction: calling .focus() on an element with a valid ARIA role fires a native focus event that the accessibility API propagates to assistive technology. Updating a CSS class does not. Developers who conflate visual highlighting with programmatic focus are the ones producing F79 failures.

Applying This

Automated testing tools catch some F79 patterns — axe-core and Deque's tooling can flag interactive elements with no accessible role or missing tabindex management. But as our research into testing methodology documents, automated tools capture at most 37% of real accessibility failures. F79 is precisely the kind of failure that requires manual screen reader testing to confirm: you have to navigate the component with NVDA or VoiceOver and listen for what gets announced.

In code review, the signal to look for is any component where keyboard navigation is implemented via keydown event listeners on non-focusable elements (<div>, <span>, <li> without role), and where focus is simulated by toggling a CSS class rather than calling .focus(). That pattern almost always produces an F79 failure.

For teams dealing with component libraries — especially third-party ones — this is a due diligence question at procurement. Ask vendors for a VPAT and test their custom widgets with a screen reader before integration. The compliance framework pressures organizations face often lead teams to accept vendor accessibility claims at face value. F79 failures in vendor components become your legal exposure, not theirs.

Failure PatternWCAG SCAPI ImpactDetection Method
Custom menu, no ARIA role4.1.2No role eventManual SR test
CSS class used as focus indicator4.1.2No focus eventCode review + SR test
tabindex managed, .focus() not called4.1.2No focus notificationManual SR test
Native element used correctlyN/A — passesFull API notificationAutomated + manual

CORS Perspective

From a Risk/Legal Priority lens, F79 sits in a legally exposed position: it directly violates SC 4.1.2, a Level A requirement, meaning it represents baseline failure, not an edge case. Under Title II, as amended by the DOJ's 2024 final rule (opens in new window), public entities are now bound to WCAG 2.1 AA — and 4.1.2 is squarely within that mandate. The operational reality is that this failure is almost entirely a build-time problem: it emerges from development practices that treat visual behavior as equivalent to programmatic behavior. Fixing it doesn't require new tooling or budget; it requires training developers on the distinction between CSS state and accessibility API state. That's a capacity investment with immediate legal risk reduction. And for any organization that has faced settlement monitoring, custom widget focus management is exactly the kind of issue that surfaces in post-settlement audits — because it's invisible to automated scans and easy to miss in initial remediation.

About the Patricia lens

A risk and legal lens. Frames findings around regulatory exposure, drawing on Title II obligations, published case law, and government compliance requirements.

Patricia is an AI analyst lens, not a human staff member. It helps frame this article through a consistent accessibility perspective.

Specialization: Government compliance, Title II, case law

View all articles using this lens →

Transparency Disclosure

This article was drafted with AI assistance and reviewed against our editorial methodology. We disclose that process so readers can judge the work clearly.