Skip to content

fix(web): make the image diff mode switcher keyboard operable - #42267

Closed
Ayaan Gazali (ayaangazali) wants to merge 1 commit into
microsoft:mainfrom
ayaangazali:fix-42266
Closed

fix(web): make the image diff mode switcher keyboard operable#42267
Ayaan Gazali (ayaangazali) wants to merge 1 commit into
microsoft:mainfrom
ayaangazali:fix-42266

Conversation

@ayaangazali

Copy link
Copy Markdown

Rationale

The Diff / Actual / Expected / Side by side / Slider row in the screenshot diff view is five bare divs with an onClick (packages/web/src/shared/imageDiffView.tsx:102-106). No role, no tabIndex, no key handling. Tab walks past the whole row, so someone looking at a failed visual comparison cannot change which image is shown without a mouse, and a screen reader is never told the controls exist. Which mode is active is signalled only by fontWeight, so that is invisible to assistive tech too.

ImageDiffView is shared, so this covers three surfaces: the html reporter result view and error view, and the trace viewer attachments tab.

The fix is the approach this repo already settled on in #41434 and used again for chips in #42149: native elements plus a focus ring, no key handlers, Enter and Space come from the platform. Here that means <button role="tab" aria-selected> inside a role="tablist", matching how TabbedPaneTab is written. aria-selected also gives the active mode a machine-readable representation it did not have.

The inline modeStyle object is replaced by a class in a new imageDiffView.css, which is how every other component in this tree is structured, and is what lets the focus ring use the shared --vscode-focusBorder token instead of the browser default.

Rendering is unchanged. I measured every switcher's box and computed font weight before and after against the same story, and the position, size and weight are identical for all five.

Test

imageDiffView.spec.ts gets one keyboard case: focus Side by side, press Enter, assert it becomes selected and that two images are shown. On current main it fails at toBeFocused because no element matches role=tab at all.

reporter-html.spec.ts asserted the row via .locator('div'), which is now .getByRole('tab'). That test still pins the same five labels in the same order.

Fixes#42266


apologies if I have misjudged anything here, I traced it myself and leaned on claude code to check my approach lined up with how the repo already does keyboard support rather than inventing a new pattern. very happy to be corrected. freshman in college trying to contribute something real :)

The Diff / Actual / Expected / Side by side / Slider switcher in the
screenshot diff view is five plain divs with an onClick, no role, no
tabIndex and no key handling. Tab walks past all of them, so a keyboard
user looking at a failed visual comparison cannot change which image is
shown, and a screen reader is never told the controls exist.
Render them as native buttons in a tablist, the same way tabs and chips
were converted in microsoft#41434 and microsoft#42149, with a focus ring from the shared
--vscode-focusBorder token. The inline style object is replaced by a
class, so the file gets its own stylesheet like the other components.
CopilotAI lite review requested due to automatic review settings August 16, 2026 05:41

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Image diff mode switcher (Diff / Actual / Expected / Side by side / Slider) is mouse-only

3 participants

@ayaangazali@yury-s