mgifford/accessibility-skills/speech-recognition

Claude Code and agent skill by mgifford/accessibility-skills

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Load this skill whenever the project must support speech input or voice control — dictation, "click by voice" grammars, Dragon NaturallySpeaking, Voice Control (iOS/macOS), Voice Access (Android), or any interface where users activate controls by speaking. Under no circumstances let an aria-label override a visible label without keeping the visible text intact and in order. Absolutely always ensure the accessible name contains the visible label, and load alongside keyboard/SKILL.md since speech tools commonly emulate keyboard and pointer input.

Install

npx vskill@latest install mgifford/accessibility-skills/speech-recognition

SKILL.md

Speech Recognition Accessibility Skill

Canonical source: examples/SPEECH_RECOGNITION_ACCESSIBILITY_BEST_PRACTICES.md in mgifford/ACCESSIBILITY.md
This skill is derived from that file. When in doubt, the example is authoritative.

Apply these rules when implementing or reviewing any interface that must support speech input or voice control. Load alongside `keyboard/SKILL.md` — speech tools often rely on keyboard and pointer emulation, so keyboard requirements are a foundation, not a substitute.


Core Mandate

Speech recognition can dictate text, navigate interfaces, activate controls, emulate keyboard input, and operate a pointer. Speech recognition is not the same as speaker recognition — speech recognition interprets words and commands; speaker recognition tries to identify who is speaking.

Core principles:

  1. Use visible, persistent labels — people must be able to determine what to say without guessing a hidden name
  2. Match visible labels and accessible names — if a control has visible text, its accessible name must contain that text
  3. Use native semantics — correct HTML names/roles/states/values/keyboard behavior give speech tools reliable information
  4. Support more than direct label activation — keyboard emulation, name/number overlays, and pointer emulation vary by product
  5. Do not require fine pointer control — provide alternatives to dragging, path gestures, and precise spatial interaction
  6. Accept input from more than key events — dictation, paste, and autocomplete may change a field without firing expected keystrokes
  7. Provide clear feedback — expose changed state, errors, confirmations, and results visually and programmatically
  8. Test the supported environments — commands, overlays, and behavior vary by product, platform, and version

Who uses speech input: people with limited movement/strength/dexterity/ reach/endurance; repetitive strain injuries, pain, tremors, or fatigue; people using speech instead of or alongside a keyboard/pointer; people with cognitive/learning disabilities who find dictation easier than typing; temporary or situational limitations; people combining speech with a screen reader, magnifier, or switch. Speech users are not necessarily sighted — do not design or test on the assumption that everyone using speech can see a label, overlay, pointer, focus indicator, or visual result.


Severity Scale (this skill)

LevelMeaning
CriticalA control cannot be activated by any speech-tool method (name, overlay, or keyboard/pointer emulation)
SeriousAccessible name doesn't contain the visible label; validation depends only on keydown and silently rejects dictated/pasted input
ModerateRepeated controls are hard to disambiguate; icon-only control has no accessible name
MinorHidden context inserted before rather than after the visible label; inconsistent localization of names

Critical: Visible Labels Must Be Contained in the Accessible Name (WCAG 2.5.3)

For a component with visible text or an image of text, the accessible name must contain that visible text — having it at the start of the name is documented best practice, not an additional normative requirement.

html
<!-- Prefer: native text as the name -->
<button type="submit">Save</button>
<!-- Wrong: accessible name is "Confirm changes", not "Save" -->
<button type="submit" aria-label="Confirm changes">Save</button>
<!-- Acceptable when extra context is genuinely needed -->
<button type="submit" aria-label="Save document">Save</button>

aria-label/aria-labelledby can override names derived from child content — inspect the computed accessible name rather than assuming every labeling source combines. Do not use placeholder text as the only label — it can disappear during dictation and isn't a substitute for a programmatically associated <label>.

Keep visible words contiguous and in order:

html
<!-- Good: visible label starts the accessible name -->
<button>Delete <span class="visually-hidden">quarterly report</span></button>
<!-- Avoid: hidden words interrupt the visible label -->
<button aria-label="Delete the quarterly report permanently">Delete report</button>

The second example contains "Delete" and "report" but inserts other words between them — some speech tools may not match the phrase a user sees. A hidden prefix (context appearing before the visible word) is not automatically a 2.5.3 failure if the visible text still appears intact, but it can still make direct label activation harder — prefer not to put hidden words before the text a person sees. Put format hints/constraints in an aria-describedby description, not the name.


Serious: Disambiguate Repeated Controls Without Renaming Them

Repeated labels ("Edit", "Delete", "Read more") can cause a speech tool to present several matches — not automatically a conformance failure, but it increases effort. Prefer specific visible labels when concise:

html
<a href="/services">Read about services</a>
<a href="/products">Read about products</a>

For compact repeated actions, add contextual text after the visible action:

html
<li>
Billing address
<a href="/account/billing/edit">Edit <span class="visually-hidden">billing address</span></a>
</li>

Do not make accessible names unique by replacing or reordering the visible label — "Modify billing address" is not a good hidden name for a visible "Edit" link.


Moderate: Icon-Only Controls

Still need an accessible name under WCAG 4.1.2 (2.5.3 doesn't apply when there's no visible text label):

html
<button type="button" aria-label="Close dialog">
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
<path d="M6 6 18 18M18 6 6 18"></path>
</svg>
</button>

Persistent visible text is usually more discoverable than an icon alone. A tooltip appearing only on hover/focus is not a persistent visible label — a person must first discover or target the control before it helps. If an icon-only design is retained: use a concise localized name; use a familiar icon consistently; provide adequate target size/spacing; ensure name/number overlays identify it; don't use color or position as the only description; test with the supported speech tools.


Critical: Native Semantics and Keyboard Operation

Speech tools often use accessibility APIs, keyboard emulation, or pointer emulation — native HTML supplies reliable role/name/state/value/focus/ activation behavior for free.

html
<!-- Wrong: not a reliable button -->
<div class="button" onclick="saveDocument()">Save</div>
<!-- Correct -->
<button type="button" onclick="saveDocument()">Save</button>

Do not publish tables claiming a particular spoken phrase always works for every role — command grammar differs by speech product, platform, locale, and version. Correct semantics still improve compatibility and remain required for other AT. All functionality must be available through a keyboard interface (unless the function requires path-dependent input) — speech software can use that keyboard interface as one operating method. For custom widgets: use the correct role only when no native element suffices; implement the expected keyboard interaction; expose name/state/properties/ value; update programmatic state when visual state changes; follow an established APG pattern. See skills/keyboard/SKILL.md.


Serious: Dictation and Text Entry Must Not Depend Only on keydown

Speech dictation may insert, replace, or delete text without producing the same keydown sequence as a physical keyboard.

js
// Correct: responds to value changes regardless of input method
search.addEventListener('input', () => updateSuggestions(search.value));
// Wrong: dictation, paste, and autocomplete may bypass this logic
search.addEventListener('keydown', event => updateSuggestions(event.key));

Text-entry controls should: use native inputs/textareas; have persistent visible labels; expose format instructions and errors programmatically; accept paste, dictation, autocomplete, and programmatic value changes; allow editing/correction before submission; avoid short time limits or speech-rate assumptions; not require a specific punctuation phrase when another valid value is acceptable; preserve entered content after validation errors. Do not infer that a lack of `keydown` means no input occurred — validate the current value at the appropriate event and again at submission.


Serious: Dragging, Gestures, and Spatial Interaction Need Direct Alternatives

Dragging with a speech-controlled pointer can require several commands and precise timing.

html
<!-- Reordering alternative -->
<li>
Budget report
<button type="button">Move up <span class="visually-hidden">Budget report</span></button>
<button type="button">Move down <span class="visually-hidden">Budget report</span></button>
</li>

If drag-and-drop is also available, both methods should update the same model and provide confirmation. For sliders, pair the draggable control with a direct entry or step control:

html
<label for="volume">Volume</label>
<input id="volume" type="range" min="0" max="100" value="50">
<label for="volume-value">Volume percentage</label>
<input id="volume-value" type="number" min="0" max="100" value="50">

WCAG 2.5.7 requires author-created dragging to have a single-pointer alternative unless essential — a keyboard-only alternative does not necessarily satisfy this single-pointer requirement. Path-based or multipoint gestures need a single-pointer alternative under 2.5.1 too, unless the gesture is essential. See skills/touch-pointer/SKILL.md.


Moderate: Focus, Scrolling, and Overlays

Some speech users emulate keyboard commands or combine speech with another input method — focus order, visibility, and unobscured controls remain important. Sticky headers/cookie notices/chat launchers must not hide a focused component (WCAG 2.4.11).

css
html { scroll-padding-block-start: var(--sticky-header-height, 4rem); }
:focus-visible { scroll-margin-block: 0.5rem; }

Ensure: focus doesn't move behind an open modal; closing a dialog returns focus to a logical control; direct activation scrolls the target into view when needed; overlays can be dismissed without dragging or precise pointer movement; no essential control is permanently covered at supported viewport sizes. Speech input can be combined with a screen reader, so interaction must not depend on seeing focus or an overlay.


Serious: Expose State, Results, and Error Feedback Programmatically

html
<button type="button" aria-expanded="false" aria-controls="filters-panel">Filters</button>
<div id="filters-panel" hidden><!-- Filter controls --></div>

Update both aria-expanded and hidden together — similarly for aria-pressed, aria-checked, selected tabs, and slider values.

html
<p id="cart-status" role="status" aria-atomic="true"></p>

Use visible text and an appropriate status-message pattern (see skills/aria-live-regions/SKILL.md) — don't move focus for every confirmation. For errors needing immediate correction, associate the error with the field and use the form's established error-summary strategy. Avoid feedback that is: shown only by color/animation/icon change; available only on hover; removed before it can be perceived; announced repeatedly for every dictated character; hidden from accessibility APIs; disconnected from the control that caused it.


Moderate: Labels, Symbols, and Localization

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/mgifford/accessibility-skills/speech-recognition/badge)](https://verified-skill.com/skills/mgifford/accessibility-skills/speech-recognition)

Something wrong with this skill or its page? Tell us.