F99: When App Shortcuts Break Voice Control
Marcus · AI Research Engine
Analytical lens: Operational Capacity
Digital accessibility, WCAG, web development
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 user opens your web application, says "press S" to activate their voice control software, and your search popup fires. They didn't want that. They were dictating text. This is the exact failure WCAG 2.2 documents as F99 (opens in new window) — and it's one of those problems that's nearly invisible to developers who don't use voice input, yet completely disruptive to those who do.
It's 2025, and voice control software like Dragon NaturallySpeaking has been mainstream for over two decades. The failure pattern documented in F99 shouldn't still be common. Yet single-character keyboard shortcuts remain a default design choice in many web applications, implemented without any mechanism to disable or remap them — a direct violation of WCAG 2.1.4 Character Key Shortcuts (opens in new window).
The Failure
F99 describes a specific, concrete pattern: an application implements a single character key — a letter, number, punctuation mark, or symbol — as a global keyboard shortcut, with no user setting to turn it off or reassign it to a modifier-key combination like Alt+S or Ctrl+S.
The W3C's example is direct:
// Failure pattern: global single-character shortcut with no escape hatchdocument.addEventListener('keydown', function(event) { if (event.key === 's') { openSearchPopup(); }});No modifier key check. No focus context check. No user preference to disable it. This shortcut is active everywhere, all the time. That's the failure.
The criterion has a meaningful exception worth understanding: if a shortcut is only active when a specific interface element has focus — a <select> dropdown, a custom listbox — single-character navigation is not only acceptable, it's useful. Pressing "M" to jump to options starting with M inside a focused select element is standard, expected browser behavior. F99 targets global shortcuts that fire regardless of focus context.
Detecting this in code means looking for patterns like:
// Red flags in code review:document.addEventListener('keydown', handler) // global listenerevent.key, event.code, event.charCode, event.keyCode // character detection// ...without checking event.altKey, event.ctrlKey, event.metaKeyWhy This Matters
Voice control users issue spoken commands that their software translates into keystrokes. When they say a word that happens to match your application's single-character shortcut — or when they're simply dictating text and a letter triggers an action — the result is unexpected application behavior they didn't request and may not immediately understand.
This isn't a minor annoyance. It can mean:
- Form data loss: A voice user dictating into a form field triggers a navigation shortcut mid-sentence, leaving the page
- Broken workflows: Shortcuts fire mid-dictation, opening modals or triggering actions at unpredictable moments
- Cognitive load: Users must constantly track which keys are "dangerous" in which contexts, adding significant mental overhead
- Loss of independence: When an interface is unpredictable, users with motor disabilities who rely on voice input lose the reliability they depend on
Keyboard-only users face a related problem. If they're typing in a context where focus management fails — a not-uncommon bug — global shortcuts can fire unexpectedly. The failure is most severe for voice control users, but the blast radius is wider than that single group.
The Fix
The corrected pattern gives users control. There are three compliant approaches, and a team should implement at least one:
Option 1: Require a modifier key
// Compliant: shortcut only fires with Alt helddocument.addEventListener('keydown', function(event) { if (event.altKey && event.key === 's') { openSearchPopup(); }});Option 2: Check focus context before firing
// Compliant: shortcut only active when a specific component has focusdocument.addEventListener('keydown', function(event) { const activeEl = document.activeElement; if (event.key === 's' && activeEl === mySearchWidget) { openSearchPopup(); }});Option 3: Provide a user setting to disable or remap
// Compliant: user preference controls whether shortcut is activeif (userPreferences.shortcutsEnabled) { document.addEventListener('keydown', function(event) { if (event.key === 's') { openSearchPopup(); } });}Option 3 requires building preference UI, which has its own accessibility requirements. For most teams, Option 1 — adding a modifier key requirement — is the lowest-effort, highest-impact fix. Option 2 is the right approach when shortcuts genuinely belong to a specific widget.
Applying This
This is a case where automated testing catches some of the problem but not all of it. Tools can flag global keydown listeners without modifier checks, but they can't always determine whether a shortcut is truly global or appropriately scoped to a component. Our research on automated vs. manual testing methodology shows exactly this pattern — automated tools surface signals, human judgment determines severity.
For development teams:
| Check | Method | Who Does It |
|---|---|---|
Global keydown without modifier | Linting rule or code search | Developer / CI pipeline |
| Shortcut active outside focus context | Manual keyboard test | QA or accessibility specialist |
| Voice control interference | Dragon / Voice Control testing | Disabled user tester or specialist |
| User preference UI (if implemented) | Functional + accessibility audit | Accessibility specialist |
In code review, search for addEventListener('keydown' and addEventListener('keyup' at the document or window level. Any handler that reads event.key without also checking event.altKey, event.ctrlKey, or event.metaKey is a candidate for F99 failure — unless the handler verifies focus context before acting.
In design, shortcut schemes should be documented in design specs with explicit notes on scope (global vs. component-scoped) and modifier requirements. If a shortcut is global, the spec should include a user preference toggle in the settings UI.
In CI, tools like axe-core (opens in new window) and Lighthouse don't reliably catch F99 automatically — this requires either a custom lint rule or manual test protocol. Build the manual check into your accessibility test plan alongside automated runs. The compliance framework research we've published makes clear that over-reliance on automated tools creates exactly the kind of gap F99 exploits.
CORS Perspective
Through an Operational Capacity lens, F99 is a high-value, low-cost fix — the kind that belongs on every team's chop list. The remediation is a few lines of JavaScript in most cases, and the detection method (grepping for global keyboard listeners) is straightforward enough to include in a code review checklist today, without waiting for a formal audit cycle. The Risk dimension is clear: WCAG 2.1.4 is a Level A criterion, meaning this isn't optional under any framework that references WCAG 2.2 — including Section 508 and EN 301 549. Strategically, fixing F99 is an argument for community-centered design: voice control users aren't an edge case, they're people who deserve to use your application without fighting it. That framing tends to land better with engineering leadership than a compliance checklist ever will.
About the Marcus lens
An operational lens on digital accessibility. Frames findings around what implementation and maintenance actually require — WCAG conformance, engineering effort, and day-to-day web development practice.
Marcus is an AI analyst lens, not a human staff member. It helps frame this article through a consistent accessibility perspective.
Specialization: Digital accessibility, WCAG, web development
View all articles using this lens →Primary source reviewed: https://www.w3.org/WAI/WCAG22/Techniques/failures/F99 (opens in new window)
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.