Skip to content

fix: prevent message actions from repeating bot responses - #5865

Open
ahonamatata wants to merge 2 commits into
microsoft:mainfrom
ahonamatata:users/asalsa/message-actions-a11y
Open

ahonamatata wants to merge 2 commits into
microsoft:mainfrom
ahonamatata:users/asalsa/message-actions-a11y

Conversation

@ahonamatata

@ahonamatata ahonamatata commented Oct 2, 2026 •

Copy link
Copy Markdown

Fixes #5849

Changelog Entry

  • Fixed screen readers repeating the full bot response when focus enters message actions such as Copy, Like, or Dislike, resolving #5849, by @asalsa

Description

Windows Narrator repeats an entire bot response when keyboard focus first enters native message actions such as Copy, Like, or Dislike. The controls already expose concise accessible names, so adding another button label does not break the relationship that causes the repeated response.

Latest-main source still labeled the role-less outer stacked-layout container with the inner message row. The label target contains the greeting, full response, and action toolbar. A live accessibility-tree reproduction using published botframework-webchat@4.19.1, which contains the same relationship, showed that the actions had concise names while an ancestor accessible name contained the full response. This explains why the Agent Builder article-level workaround does not resolve the nested Web Chat context announced when focus enters an action.

This change removes the redundant accessible-name relationship from the outer layout and removes its now-unused generated ID. The inner message group and transcript article continue to expose message context and navigation semantics.

Reproduction:

  1. Render a long bot response with AllowCopy, LikeAction, and DislikeAction.
  2. Set feedbackActionsPlacement to activity-actions.
  3. Start Narrator in Edge.
  4. Move focus into Copy, Like, or Dislike.
  5. Before this change, Narrator announces the full response as ancestor context before the concise action name.
  6. After this change, the action no longer has an ancestor accessible name derived from the response.

Manual Edge plus Narrator validation passed for the #5849 first-focus announcement: keyboard-driven focus on Copy announced only “Copy, button,” and arrow navigation announced Like and Dislike without repeating the response. A separate transcript activation regression remains: activating the blue-outlined transcript activity reports “Item has no primary action” instead of moving focus into the message actions.

Design

The fix breaks the proven causal relationship instead of changing button labels, moving the toolbar, or modifying the activity article. It does not change localization, DOM order, keyboard order, or focus order. The message row remains role="group" with aria-roledescription="message", and transcript navigation remains represented by its article active descendant.

StackedLayoutRoot has two callers. The part-grouping caller never supplied the removed label prop, and the message-layout caller was its only user. The generated message-row ID had no remaining caller after removing the outer relationship.

Specific Changes

  • Removed aria-labelledby from the role-less stacked-layout container.
  • Removed the generated ID and prop wiring used only by that relationship.
  • Added an HTML integration regression with native Copy, Like, and Dislike.
  • Asserted computed AX action names, absence of response-derived ancestor AX names, message grouping, and transcript article navigation.
  • Added a test-harness RPC for Selenium's result-returning DevTools command.
  • Updated CHANGELOG.md.

Validation:

  • Passed npm clean-install --userconfig .npmrc.
  • Passed npm run build-browser on Windows.
  • Passed full npm run build for the PR commit in an isolated Linux container. The archive's CRLF shell scripts were normalized only inside the disposable validation volume.
  • Passed npm test -- --testPathPattern "__tests__/html2/accessibility/messageActions\.html$" in the documented Selenium Grid through the Linux validation container: 1 suite and 1 test passed.
  • Passed .\node_modules\.bin\eslint.cmd --report-unused-disable-directives --max-warnings 0 packages\component\src packages\test\harness\src.
  • Passed npm run precommit:typecheck --workspace ./packages/component.
  • Passed npm exec prettier -- --check for every changed component, HTML test, and harness file.
  • Passed git diff --check.
  • Reconfirmed live Chrome AX causal evidence against published botframework-webchat@4.19.1, not the PR build: action names were Copy, Like, and Dislike; the response-bearing ancestor name existed before removing the outer relationship and disappeared afterward; the message group and transcript article remained.
  • Windows Jest discovery remains environment-specific in this worktree because its resolved glob contains BotFramework-WebChat\.worktrees; the same focused test passed through the Linux Selenium Grid route.
  • Passed manual Edge plus Narrator first-focus validation using a keyboard-only helper that moved DOM focus into Copy. Narrator announced Copy, Like, and Dislike without repeating the bot response.
  • Observed separately: while the transcript activity has the blue active-descendant outline, Narrator reports “Item has no primary action” and does not move focus into the controls. The repository contract says Enter should work with or without scan mode, but this PR does not change BasicTranscript, ActivityRow, or FocusTrap.
  • GitHub pull-request validation remains action_required with zero jobs until a maintainer authorizes the workflow.
  • I have added tests and executed them locally
  • I have updated CHANGELOG.md
  • I have updated documentation

Review Checklist

This section is for contributors to review your work.

  • Accessibility reviewed (tab order, content readability, alt text, color contrast)
  • Browser and platform compatibilities reviewed
  • CSS styles reviewed (minimal rules, no z-index)
  • Documents reviewed (docs, samples, live demo)
  • Internationalization reviewed (strings, unit formatting)
  • package.json and package-lock.json reviewed
  • Security reviewed (no data URIs, check for nonce leak)
  • Tests reviewed (coverage, legitimacy)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 068c5ef2-5e03-4d29-8666-f2b34b1bcc92
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 068c5ef2-5e03-4d29-8666-f2b34b1bcc92

Copilot AI 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 review overview

🟢 Approval recommended

The focused production change is supported by accessibility-tree regression coverage and reported manual Narrator validation.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes #5849 by removing the redundant accessible-name relationship that caused screen readers to repeat bot responses when focusing message actions.

Changes:

  • Removes obsolete ARIA label and generated ID wiring.
  • Adds Chrome accessibility-tree regression coverage.
  • Extends the test harness to return DevTools command results.
File Description
CHANGELOG.md Records the accessibility fix.
__tests__/​html2/​accessibility/​messageActions.html Tests action names and surrounding accessibility semantics.
packages/​component/​src/​Activity/​StackedLayout.tsx Removes generated ARIA ID wiring.
packages/​component/​src/​Activity/​StackedLayoutRoot.tsx Removes the problematic aria-labelledby.
packages/​test/​harness/​src/​browser/​proxies/​host.js Exposes the new DevTools RPC.
packages/​test/​harness/​src/​host/​common/​host/​index.js Registers the RPC implementation.
packages/​test/​harness/​src/​host/​common/​host/​sendAndGetDevToolsCommand.js Returns result-bearing DevTools responses.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

This branch has not been deployed

No deployments
Sign up for free to 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.

{Linked:Bug34037190}[Accessibility] Message action buttons announce the entire bot response

2 participants