anthropics / anthropics/claude-code

[BUG] Claude Code Desktop (Windows): slash command menu in the Code tab composer is silent for screen readers (NVDA)

Đang mở
#94,353 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
area:a11y area:desktop bug platform:windows
Ngôn ngữ chính
Python
Star
145k
Fork
23.1k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code

### What's Wrong?

In Claude Code Desktop (the Code tab of Claude Desktop 1.52386.6.0 on Windows 11, Claude Code 2.1.270), the slash command menu that opens when typing `/` in the prompt composer (for example `/rename`) is completely silent for the NVDA screen reader. NVDA announces nothing when the menu opens, nothing while arrowing through it, and not which command is highlighted. Because ArrowUp/Down, Tab and Enter are taken over by the menu, a blind user cannot tell what Enter or Tab will do, so entering a command such as `/rename New title` becomes guesswork.

### What Should Happen?

The composer exposes the menu as an autocomplete popup (ARIA 1.2 combobox pattern): NVDA announces that suggestions are available, reads the highlighted command and its description as the arrow keys move, and Enter/Tab behave predictably (WCAG 4.1.2 Name, Role, Value; 1.3.1 Info and Relationships; 4.1.3 Status Messages). The `/resume` and `/rewind` pickers in the same app already do this correctly.

### Error Messages/Logs

```shell
None; this is an accessibility-tree problem.
```

### Steps to Reproduce

1. On Windows 11, start NVDA and open Claude Desktop → Code tab, with a Claude Code session.
2. Focus the prompt composer and type `/ren`.
3. Press ArrowDown/ArrowUp a few times, then press Enter or Tab.
4. Observe: NVDA says nothing at any step; the menu is only visible on screen.

### Claude Model

Opus

### Is this a regression?

I don't know

### Last Working Version

_No response_

### Claude Code Version

2.1.270 (Claude Code), bundled with Claude Desktop 1.52386.6.0

### Platform

Anthropic API

### Operating System

Windows

### Terminal/Shell

Other (Claude Code Desktop, Code tab)

### Additional Information

#### Root cause (from the shipped bundle `resources/ion-dist/assets/v1/`, minified names)

1. **Focus stays in the editor, and the editor does not reference the menu.** The menu is a TipTap suggestion plugin (`slash-command-suggestion`, `char:"/"`) in `shared-13-D4O01Gj8.js`. On mount the menu calls `i.view.dom.focus()`, so DOM focus stays in the ProseMirror contenteditable. That element never gets `role="combobox"`, `aria-expanded`, `aria-controls`/`aria-owns` or `aria-activedescendant`: none of these attributes occur in that file. The popup element is appended straight to `document.body` (`...ownerDocument.body.appendChild(o)`), with no relationship to the editor in the accessibility tree.
2. **The highlighted row is only highlighted visually.** In the lazy chunk `ccc334009-BDcyQYO5.js` (`SlashCommandMenuPopupBody`) each row is `role:"menuitem", tabIndex:-1` with `"data-highlighted": n ? "" : void 0`. Rows have no `id` and no `aria-selected`, and never receive focus. The active row element is tracked (`setActiveRowElement`) only to `scrollIntoView` it. The container in `shared-12-BzDv77xE.js` is a `role:"menu"` div without an `id` or accessible name. Long lists are virtualised (`getVirtualItems()`), so the highlighted row may not be in the DOM until scrolled to.
3. **Navigation keys are swallowed before the screen reader can observe a change.** The menu provider (`OL`, "useSlashCommandMenu", `shared-12-BzDv77xE.js`) adds a capture-phase `keydown` listener on the document (`s.addEventListener("keydown",B,!0)`). For ArrowUp/Down/Left/Right, Tab and Enter it calls `preventDefault()` and `stopImmediatePropagation()` and only updates React state (`activeIndex`). The suggestion plugin's `onKeyDown` in `shared-13` also returns `true` for these keys while items are visible. Neither the caret, the focus nor `aria-activedescendant` changes, so NVDA has nothing to announce.
4. **No live-region fallback.** Nothing announces "menu opened", the result count or the highlighted item. The only live region in this area is the skill argument hint (`data-skill-arg-hint-sr`); the "Type to filter" hint (`$D`) is a purely visual span.
5. **Enter/Tab depend on state the user cannot perceive.** In `OL`'s key handler Tab always activates the highlighted row; Enter either activates it or only closes the menu, depending on whether the user navigated with the arrows and whether the highlighted row matches the typed text (`e.key==="Enter"&&D===0&&!O&&!A&&(...)?r()`). Typed skills are also auto-resolved on a timer once a space follows a unique match (`claudeai.slash_command_menu.auto_resolved`).

#### Suggested fix

- On the ProseMirror contenteditable while the menu is open: `role="combobox"` (or keep `textbox` and add the combobox attributes), `aria-haspopup="listbox"`, `aria-autocomplete="list"`, `aria-expanded` bound to the menu state, and `aria-controls` pointing to the menu's id (TipTap: `editorProps.attributes`, or set them in the suggestion's `onStart`/`onExit`).
- Popup `role="listbox"` with an id and an accessible name ("Commands"); rows `role="option"` with a stable `id` and `aria-selected`; keep `aria-activedescendant` on the editor in sync with `activeIndex` (and the submenu index). The `/resume` picker (`cli-resume-listbox`, `cli-resume-opt-N`) and the `/rewind` list (`rewind-opt-N`) in `c5610fbe3-0RHH64gR.js` already implement this pattern.
- Keep the active option in the DOM whenever it is referenced (virtualised list).
- Add a polite live region with the result count when the menu opens or the filter changes, since `aria-activedescendant` changes on a contenteditable are not always announced by Chromium + NVDA.
- Make Enter predictable: when the user has not navigated and the typed text is a complete command with arguments (`/rename New title`), submit the text as typed.

#### Notes

The root cause was established by reading the shipped bundle; the symptom is reproduced by the reporter with NVDA. No live instrumentation was run. Related report by the same reporter about focus handling in Claude Code Desktop: #94246.

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.