Chat panel: Send/Stop button has no accessible name (WCAG 4.1.2)

Status Open
Reported on v2.1.268
Maintainer reply None cached
Activity 0 comments · opened Sep 12, 2026

Summary

First — thank you for the screen-reader work in the chat panel. The status announcements, the
labeled transcript region, and the hidden per-turn headings are genuinely well done, and it's
great to see it shipped and documented.

While testing the chat panel with Windows UI Automation (the same accessibility API screen readers
consume), I hit one control that doesn't match the "works with screen readers" promise: the
Send/Stop button has no accessible name.
A screen reader announces it as just "button," in both
its Send and its Stop state — so a screen-reader user can't tell whether pressing it will send
their message or stop the running agent (which discards in-progress work).

It's a small, very fixable gap on an otherwise-solid feature — likely a one-line aria-label. Details
below in case they're useful.

  • Extension: Claude Code for VS Code, 2.1.268 (also on 2.1.269).
  • OS: Windows 10.

---

The specific issue

The chat footer's Send/Stop button is a single control whose function flips with state — Send when
the input has text, Stop/interrupt while the agent is running with an empty box. In both states it
has no accessible name.

Measured with UIA (what a screen reader reads):

| State | Function | UIA Name | aria-label | ClassName |
|---|---|---|---|---|
| empty box, agent running | Stop | "" | none | sendButton_gGYT1w |
| text in box | Send | "" | none | sendButton_gGYT1w |

Name, LegacyIAccessible.Name, HelpText, and Description are all empty; AriaRole is
button with no label. Since the accessible name is computed from every source (aria-label,
aria-labelledby, title, child text/SVG title), an empty result means no labeling mechanism is
present. This is a WCAG 2.2 SC 4.1.2 (Name, Role, Value) gap — and it's on the panel's most
consequential control, since one of its two functions discards in-progress work.

It's visible in the shipped webview bundle (extension/webview/index.js), the footer button render:

D("button",{ type:"submit", disabled:!$.busy.value&&!X, className:_7.sendButton,
  "data-permission-mode":J,
  onClick:(B0)=>{ if($.busy.value&&!X) B0.preventDefault(), $.interrupt() },  // Stop behavior
  children:E })                                                               // E = the icon only

No aria-label, aria-labelledby, or titlechildren is just the icon (the send/stop icon
swap is visual only). For contrast, the same bundle labels ~23 other controls, including the
side-question feature's send button two lines away (aria-label: "Send side question") and the
message box (aria-label: "Message input") — so it really does look like this one control was just
missed, not a deliberate choice.

It's long-standing, not a recent regression. Checking the webview bundle across the versions on
Open VSX, the button is a single, unlabeled Send/Stop control in every one — including 2.1.236,
where chat-panel screen-reader support was introduced:

| Version | Accessible name on the Send/Stop button |
|---|---|
| 2.1.209 (oldest on Open VSX) | none |
| 2.1.236 (screen-reader support introduced) | none |
| 2.1.259 | none |
| 2.1.268 / 2.1.269 (current) | none |

Credit where due: the live region

There's a nicely-built visually-hidden aria-live="polite" region that announces state ("Claude is
working." / "Ready for your input." / etc.). A user following the announcements can infer the
button's current function, which is probably why this hasn't been noticed. It just doesn't give the
button itself an accessible name, so a user navigating control-by-control (Tab) still lands on an
unnamed "button." So the live region helps, but doesn't cover this specific case.

---

Two small related doc notes (only if helpful)

  1. How to stop/interrupt isn't documented for keyboard/AT users. Sending is covered (Enter

sends, per useCtrlEnterToSend), but the "Use a screen reader" section doesn't name the
Send/Stop control or a keyboard interrupt, and I couldn't find a documented stop/interrupt
shortcut for the extension anywhere in the docs. Once the button has a name, a line noting how to
stop would close the loop.

  1. The changelog for this area is hard to find. The entry that seems to describe the Send/Stop

button's accessibility work isn't in the docs or the GitHub release notes that I could find — I
only saw it via a third-party changelog aggregator. Surfacing it in first-party notes would help
people (and AT testers) find what shipped.

---

Suggested fix

A state-aware accessible name on the button resolves the 4.1.2 gap — roughly:

aria-label={busy ? "Stop response" : "Send message"}

(with a matching title if you like). One nice bonus: an accessible name is also what voice-control
software (Dragon, Windows Voice Access, macOS Voice Control, Talon) uses to target a control — those
users say "click <name>" — so the same one-line change also makes the button usable by voice,
not just by screen readers.

Happy to provide any more detail, repro steps, or the UIA probe output if useful. Thanks again for
building this — it's a genuinely good tool, and the accessibility work already in it is the reason
this gap stood out.

---

<details>
<summary>How this was measured</summary>

  • Accessible name: Windows UI Automation client, reading Name, LegacyIAccessible

(Name/Description/Role), HelpText, AriaRole, AriaProperties on the sendButton_* element in
both Send and Stop states.

  • Source: extension/webview/index.js from the installed extension and from the Open VSX .vsix

packages for the versions in the table.

  • Docs referenced: code.claude.com/docs/en/vs-code ("Use a screen reader") and

code.claude.com/docs/en/accessibility.
</details>

View original on GitHub ↗