VS Code Minimap: the keyboard scrollbar (aria-controls, aria-valuenow from the real range)

Merged
TE
11d ago
+153-8

Part of the VS Code Minimap stack. Land order: #25185 (the minimap), then this PR (its keyboard scrollbar), then #25280 (placeholder looks, bench gate). It is stacked on #25185, so review only its top commit (+103/āˆ’6). Split out of #25185 to keep that PR near the size cap.

Leo's words

minimap? i dont see any command for the vscode minimap

What this adds

In #25185 the minimap is a pointer surface (aria-hidden), and the transcript keeps its own keyboard scrolling. This PR makes the track a keyboard scrollbar:

  • Keyboard: a Tab stop labelled "Chat minimap" (chatMinimap.label, already in the catalog from #25275, all locales). Arrow, Page, Home and End scroll the transcript. It doesn't trap focus, and it shows a focus ring.
  • aria-controls: names the transcript scroller, which is given an id when it has none. The id is removed on unmount if the minimap gave it.
  • aria-valuenow: the share of the scroller's own range scrolled (scrollHeight āˆ’ clientHeight), so it reads 0 at the top and 100 at the end whatever padding or dock is in the content. It is written in the view box's existing frame, focused or not, and only when the whole percent changes. Nothing is read per token: while a reply streams, the box's frame skips the transcript's own follow.
  • The canvas stays aria-hidden.

These address #25185's re-review finding 2 (aria-valuenow stale while unfocused, and its denominator double-counting padding and composer space).

Tests

webviews/test/chat-minimap.test.tsx:

  • Value: a 1000 px chat in a 600 px view reads 100 at the end, 0 at the top and 50 at 200 px, without focus.
  • Keys: on the focused control, End reads 100, Home 0, and ArrowDown 40 px of the range.
  • Attributes: the label, the Tab stop, aria-controls equal to the transcript's id, and the canvas aria-hidden.

On #25185's previous head (04f7de27) the value test fails (0 instead of 100). vp lint is clean, and chat-minimap passes 7/7.

Risk

Low. The scroll-path change is one setAttribute when the integer percent changes, inside the box's frame. Nothing else changes for pointer users.

Agent session: agent session

šŸ¤– Generated with Claude Code