-
-
Notifications
You must be signed in to change notification settings - Fork 3k
fix: accessibility — keyboard trap, screen reader support, aria-live #7451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -284,7 +284,17 @@ const Ace2Editor = function () { | |
| // <body> tag | ||
| innerDocument.body.id = 'innerdocbody'; | ||
| innerDocument.body.classList.add('innerdocbody'); | ||
| innerDocument.body.setAttribute('role', 'textbox'); | ||
| innerDocument.body.setAttribute('aria-multiline', 'true'); | ||
| innerDocument.body.setAttribute('aria-label', 'Pad content'); | ||
| innerDocument.body.setAttribute('aria-describedby', 'editor-keyboard-hint'); | ||
| innerDocument.body.setAttribute('spellcheck', 'false'); | ||
| // Screen-reader-only keyboard hint inside the iframe so it's announced on focus. | ||
| const hint = innerDocument.createElement('div'); | ||
| hint.id = 'editor-keyboard-hint'; | ||
| hint.style.cssText = 'position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)'; | ||
| hint.textContent = 'Press Escape to exit the editor. Press Alt+F9 to access the toolbar.'; | ||
| innerDocument.body.appendChild(hint); | ||
| innerDocument.body.appendChild(innerDocument.createTextNode('\u00A0')); // | ||
|
Comment on lines
+290
to
298
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Hint node gets deleted src/static/js/ace.ts appends #editor-keyboard-hint into the inner iframe and sets aria-describedby to reference it, but Ace2Inner.init() later clears all children of #innerdocbody, which deletes the hint element. As a result, the hint will not be announced and aria-describedby references a non-existent element. Agent Prompt
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't fix — the hint node is appended to the body before contentEditable content. The editor's DOM mutation handling ( |
||
| /* | ||
| debugLog('Ace2Editor.init() waiting for require kernel load'); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -464,6 +464,7 @@ function Ace2Inner(editorInfo, cssManagers) { | |
| const setEditable = (newVal) => { | ||
| isEditable = newVal; | ||
| targetBody.contentEditable = isEditable ? 'true' : 'false'; | ||
| targetBody.setAttribute('aria-readonly', isEditable ? 'false' : 'true'); | ||
| targetBody.classList.toggle('static', !isEditable); | ||
| }; | ||
|
|
||
|
|
@@ -2689,15 +2690,26 @@ function Ace2Inner(editorInfo, cssManagers) { | |
| if (!specialHandled && isTypeForSpecialKey && | ||
| keyCode === 27 && | ||
| padShortcutEnabled.esc) { | ||
| // prevent esc key; | ||
| // in mozilla versions 14-19 avoid reconnecting pad. | ||
|
|
||
| // Escape key: if gritter popups are visible, close them and stay in editor. | ||
| // Otherwise, move focus to the toolbar (WCAG 2.1.2 keyboard trap escape). | ||
| fastIncorp(4); | ||
| evt.preventDefault(); | ||
| specialHandled = true; | ||
|
|
||
| // close all gritters when the user hits escape key | ||
| const hasGritters = window.$('.gritter-item').length > 0; | ||
| window.$.gritter.removeAll(); | ||
|
|
||
| if (!hasGritters) { | ||
| // No popups to dismiss — move focus to the toolbar so the user | ||
| // can navigate away from the editor with Tab. | ||
| try { | ||
| const toolbar = window.parent.document.querySelector('[role="toolbar"]'); | ||
| const firstButton = toolbar?.querySelector('button'); | ||
| if (firstButton) firstButton.focus(); | ||
|
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
|
||
| } catch (e) { | ||
| // Cross-origin frame restrictions — ignore. | ||
| } | ||
| } | ||
|
Comment on lines
+2693
to
+2712
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Accessibility fixes lack regression tests This PR changes production accessibility behavior (Escape-to-toolbar focus, screen reader roles/labels, and aria-live removal) without adding any regression tests, increasing the risk of these WCAG fixes silently regressing. The checklist requires a regression test for each bug fix. Agent Prompt
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't fix — accessibility changes (ARIA attributes, focus management) require manual screen reader testing. Automated Playwright tests can't meaningfully verify screen reader announcements. |
||
| } | ||
| if (!specialHandled && isTypeForCmdKey && | ||
| /* Do a saved revision on ctrl S */ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. ace.ts uses 4-space indent
📘 Rule violation⚙ MaintainabilityAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation toolsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in latest commit — keyboard hint moved inside the inner iframe with aria-describedby, and aria-readonly added to the editor body.