Skip to content

Fix Voice Access numbering background controls when clipper is open (A11y MAS 4.3.1)#652

Draft
Copilot wants to merge 4 commits intomasterfrom
copilot/verify-accessibility-voice-access
Draft

Fix Voice Access numbering background controls when clipper is open (A11y MAS 4.3.1)#652
Copilot wants to merge 4 commits intomasterfrom
copilot/verify-accessibility-voice-access

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 30, 2026

When the OneNote Clipper UI is open, Voice Access displays numbered overlays on background page controls — elements that should be unreachable while the clipper is active.

The root cause: the clipper UI runs inside an iframe appended to document.documentElement, giving it a separate accessibility tree from the host page. aria-modal="true" inside the iframe cannot suppress Voice Access numbering of parent page elements. The fix must happen in the inject script, which runs in the host page context.

Since the iframe is a child of <html> (not <body>), setting aria-hidden="true" and inert on document.body hides all page content from assistive technologies while keeping the clipper iframe (a sibling of <body>) fully accessible:

<html>
  <head></head>
  <body aria-hidden="true" inert>…page content…</body>   <!-- hidden from Voice Access, pointer events disabled -->
  <iframe id="oneNoteWebClipper"></iframe>               <!-- still accessible -->
</html>

aria-hidden="true" removes body elements from the AT accessibility tree. The inert attribute additionally disables all pointer events on body elements — this is necessary because Voice Access on Windows (built on UI Automation) can also scan for elements capable of receiving pointer/mouse events independently of AT-tree visibility, so aria-hidden alone is insufficient.

Changes

  • clipperInject.ts: Set aria-hidden="true" and inert on document.body when the clipper opens, and remove both when it closes. Three cases are covered:

    • First open (constructor): body is marked inert and hidden immediately after the frame is created and shown
    • Re-open after close (toggleClipper()): body is marked inert and hidden when the frame is shown again
    • Close (hideUi handler): both aria-hidden and inert are removed so page controls are fully accessible again
  • mainController.tsx: Replace role="main" with role="dialog" and add aria-modal="true" on the main controller container, which remains beneficial for assistive technologies that can traverse same-origin iframes.

<div
    id={Constants.Ids.mainController}
    role="dialog"
    aria-modal="true"
    aria-label={Localization.getLocalizedString("WebClipper.Label.OneNoteWebClipper")} >
  • mainController_tests.tsx: Add regression test asserting role="dialog" and aria-modal="true" are present on the rendered main controller element.
Original prompt

A11y_OneNoe Clipper_Verify accessibility with Change Clipper Mode_Voice Access: Voice Access is showing numbers to the background controls.

Work Item Details

Note: Please focus on the descriptions and information that provide context about the task requirements, functionality, and implementation details. Dates, priorities, and administrative metadata are less relevant for coding tasks.

Description

Environment Details: 

Application Name: OneNote Clipper-Web

OS: Windows 11 OS build 26058.1000

Edge Dev Version: Version 123.0.2400.1 (Official build) dev (64-bit)

AT's: Voice access

Pre-Requisites:

  1. Open the URL: OneNote Web Clipper Installation

  2. Invoke the 'Get OneNote web Clipper for Microsoft Edge' button.

  3. Edge Add-ons page will appear. Invoke the Get button.

  4. OneNote Clipper will be added in edge extension section. 

  5. Expand the Extension button and turn on the OneNote Clipper Show in Toolbar button.

  6. OneNote Clipper will appear beside of the search field.

  7. Now invoke the OneNote clipper button.

  8. Sign in with V-id.

  9. Turn on Voice access.

Repro Steps:

  1. Open the Ankylosaurus - Wikipedia
  2. Now invoke the OneNote clipper button.
  3. OneNote Clipper dialog box will appear.
  4. Say command "Click Article" and observe the issue.

Actual Result:

Voice Access is showing numbers to the background controls.

Expected Result:

Voice Access should not provide the numbers to the background controls.

User Impact:

Voice access users will confuse if voice access showing numbers to the background control.

MAS Reference:

MAS 4.3.1 – No Disruption of Accessibility Features

Tags

A11yMAS; A11yRT; A11ySev3; A11yVoiceAccess; Accessbility; MAS4.3.1; OneNote; OneNote Clipper; OneNoteClipper_Web; RevW; RT-122025; RT-OneNote Clipper-Web-Feb2024; TCS-E+D; Web

RCA Analysis

Was change validated in devMain first before porting to fork?

Why was Flighting|Backout not used?

Impact of bug (# users affected):

RCA and Mitigation/Fix Details:

What are you doing to prevent this in the future?

Comments

GitHub Copilot (Sun, 01 Feb 2026 14:27:40 GMT): ⚠️ Attention Required: Missing Repository Link. Reverting the work item assignment.

The work item is missing a link to a repository branch. Without this link, I cannot work on the work item.
Please use one of the following options to link a repository:

Option A: Traditional Artifact Link

  1. Navigate to the Work Item: Open the work item in Azure DevOps.
  2. Locate the Links Section: Scroll to the Development area or the Links tab in the work item details.
  3. Add a Link to the Repository Branch:
    • Click on Add Link.
    • Select Branch from the available link types.
    • Choose the appropriate repository and branch that corresponds to this work item.
    • Assign the work item again to me.
    • Ensure you save the work item to update it properly.

Option B: Repository Tag

  1. Navigate to the Work Item: Open the work item in Azure DevOps.
  2. Add a tag using the format: copilot:repo=//@
    • Examples:
      • copilot:repo=MyOrg/MyProject/MyRepo@main
      • copilot:repo=MyOrg/MyProject/MyRepo@feature-branch
    • The branch name after @ is required.
  3. Assign the work item again to me.

Important: Use only one linking method - either artifact link OR tag, not both. Only one repository can be linked per work item.

Manda Sachin (TATA CONSULTANCY SERVICES LTD) (Sun, 04 Jan 2026 09:49:42 GMT): Issue is still repro, PFA for reference.

Edge Version: 143.0.3650.96 (Official build) (64-bit)

Work item: AB#8780932
Created via Azure DevOps


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…e=dialog and aria-modal=true

Agent-Logs-Url: https://github.com/OneNoteDev/WebClipper/sessions/dac056b7-abc8-4fe3-8c8f-59f5a34f4146

Co-authored-by: KethanaReddy7 <257986085+KethanaReddy7@users.noreply.github.com>
Copilot AI changed the title [WIP] Verify accessibility with Voice Access for OneNote Clipper Fix Voice Access numbering background controls when clipper is open (A11y MAS 4.3.1) Mar 30, 2026
Copilot AI requested a review from KethanaReddy7 March 30, 2026 08:53
@KethanaReddy7
Copy link
Copy Markdown

@copilot The current changes are not working as expected. With the clipper open, Voice Access still shows number overlays for background page elements, not just the clipper UI. Please review the current implementation, identify why the background is still being exposed, and suggest the correct fix.

…y from inject script

Agent-Logs-Url: https://github.com/OneNoteDev/WebClipper/sessions/6ec55267-0506-4b18-a277-54f3f90edcb7

Co-authored-by: KethanaReddy7 <257986085+KethanaReddy7@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 30, 2026

@copilot The current changes are not working as expected. With the clipper open, Voice Access still shows number overlays for background page elements, not just the clipper UI. Please review the curr...

The previous fix was applied in the wrong place. The clipper UI runs inside an iframe appended to document.documentElement, giving it a completely separate accessibility tree from the host page. aria-modal="true" inside the iframe can only suppress sibling elements within the iframe — it cannot prevent Voice Access from numbering elements in the parent page.

The correct fix is in clipperInject.ts (which runs in the host page context). Since the iframe is a child of <html>, not <body>, we can mark <body aria-hidden="true"> to hide all page content from AT while keeping the clipper iframe (a sibling of <body>) fully accessible:

<html>
  <head></head>
  <body aria-hidden="true">…page content…</body>  ← hidden from Voice Access
  <iframe id="oneNoteWebClipper"></iframe>        ← still accessible
</html>

Three cases are handled (commit 9fb6f3e):

  1. First open (constructor): sets aria-hidden="true" on document.body immediately after the frame is created and shown
  2. Re-open after close (toggleClipper()): sets aria-hidden="true" when showing the frame
  3. Close (hideUi handler): removes aria-hidden so page controls are accessible again

@KethanaReddy7
Copy link
Copy Markdown

@copilot Please review the code, it wasn't able to fix the issue

…s background numbering

Agent-Logs-Url: https://github.com/OneNoteDev/WebClipper/sessions/b160429a-a946-4869-9c23-834931415ee1

Co-authored-by: KethanaReddy7 <257986085+KethanaReddy7@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@copilot Please review the code, it wasn't able to fix the issue

The root gap was that aria-hidden="true" on document.body removes page elements from the ARIA accessibility tree, but Voice Access on Windows (built on UI Automation) can also enumerate elements that are capable of receiving pointer/mouse events — independently of AT-tree visibility. Elements hidden from the AT tree but still pointer-event-capable were still being numbered.

The fix (commit 271fb4c) adds the inert attribute alongside aria-hidden on document.body at all three lifecycle points:

<!-- When clipper is open -->
<html>
  <head></head>
  <body aria-hidden="true" inert>…page content…</body>  ← removed from AT tree + pointer events disabled
  <iframe id="oneNoteWebClipper"></iframe>              ← unaffected, still accessible
</html>

inert is the HTML-standard mechanism that simultaneously:

  • Removes elements from the accessibility tree (same as aria-hidden)
  • Disables all pointer events (so Voice Access cannot enumerate or activate them)
  • Removes elements from the tab/focus order

All three lifecycle points are covered: first open (constructor), re-open (toggleClipper), and close (hideUi removes both attributes).

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.

2 participants