Repository navigation
fix: #4997 give icon-only controls accessible names - #5739
Merged
Jocs merged 1 commit intoOct 18, 2026
Merged
Conversation
Icon-only controls in the editor and Preferences windows were divs, spans and icons with click handlers, so screen readers announced them without a name and Tab skipped them. Make them buttons with translated aria-labels, expose pressed and expanded state, and add a :focus-visible ring that meets 3:1 against the background in every bundled theme. Label the Preferences switches, selects, sliders and inputs with their visible descriptions, and size the keybinding and search toggle buttons to 24px.
This was referenced Oct 13, 2026
Member
|
I see that Could you make the tooltip background, text, and arrow colors follow the current theme, or at least distinguish between light and dark themes? Please also increase the delay before it appears. |
Jocs
approved these changes
Oct 18, 2026
6 of 9 tasks
Contributor
Author
|
Thanks for merging this, and for doing the tooltip theming and delay in #5788. Sorry I didn't get to it before you did. The longer delay should also help VoiceOver users who have the pointer following the VoiceOver cursor, since tooltips will open less often as they move around. |
1 task done
1 of 4 tasks
Jocs
added a commit
that referenced
this pull request
Oct 21, 2026
…button (#5830) * fix(desktop): show themed title-bar control icons and space the menu button The window-control icons (minimize/maximize/close) are only visible in dark themes because each theme recolours their SVG. #5739 changed the icon wrapper from a div to a span, so all 30 theme rules that target .frameless-titlebar-button > div > svg stopped matching and the icons fell back to the base black fill, invisible on a dark title bar. Point the rules at the element the template renders, and give .left-toolbar a gap so the document statistics no longer sit flush against the application-menu button. Closes #5828 * chore(desktop): remove titlebar style tests per review --------- Co-authored-by: Jocs <luoran1988@126.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4997
Summary
Icon-only controls across the editor and Preferences windows had no accessible name, and most of them could only be used with a mouse. With NVDA or VoiceOver running, the find bar's four buttons were read as "button" or "image button" with no name. Tab skipped the title bar, the side bar icons, the tab strip and the case/word/regex toggles entirely, because they were
<div>s,<span>s and<i>s with click handlers. Nearly every switch and select in Preferences was announced as just "switch" or "combobox".This PR fixes that for every icon-only control in the desktop renderer, following WCAG 2.2 AA:
<div>/<span>/<i>icons are now<button type="button">with a translatedaria-label. This covers the title bar (app menu, minimize, maximize/restore, close), the side bar icons, Save All / Close All, the close buttons in the tab strip and the opened-files list, New Tab, the find bar, the editor notification bar, the rename dialog, toast notifications, and the Preferences title bar. Close buttons include the file name ("Close notes.md"), so a list of them is not ten identical "Close" buttons.aria-pressed. The find bar's replace chevron exposesaria-expanded, and the app menu buttonaria-haspopup="menu".:focus { outline: none }stays. The new buttons get a 2px:focus-visiblering instead, drawn in--sideBarTitleColor. I didn't use--focusColorbecause it is 2.4–2.8:1 against the background in the default, Ayu Light and Everforest Light themes, under the 3:1 a focus indicator needs. The title colour is at least 3.1:1 in all 33 bundled themes, and a unit test checks that.display: noneuntil hover, so Tab could never reach them. They are now clipped (clip-path: inset(50%)) instead, and show on hover or keyboard focus. The tab strip's close and New Tab buttons also show on:focus-visible.titleattributes on these controls are replaced by a smallIconTooltipwrapper aroundel-tooltip, the same pattern as the media viewer (Add a zoom/pan viewer and image export for rendered diagrams #5554). It fixes two things I ran into:el-tooltipcallspreventDefaulton Enter/Space keydown of its trigger, which cancels the button's click (sotrigger-keysis cleared), and it now closes on Escape (1.4.13).bool,select,range,textBoxandfontTextBoxpass their visible description asaria-label, so the name matches the label on screen. The "learn more" link icons are buttons named "Learn more about {setting}", and the keybindings docs link is a button instead of an<a>withouthref.row-reverse, so Tab went close → maximize → minimize. They are now in DOM order, left to right.New strings:
titleBar.*(application menu, minimize, maximize, restore, close),editor.tabs.close("Close {name}") andpreferences.learnMore, added to all 12 locales. Minimize and Close reuse each locale's existing translations.Screen reader results
Same keyboard walk through the window, before and after. The NVDA output is from its speech log, and the VoiceOver output is from its "last phrase".
One design note: the tooltips open on hover only, not on keyboard focus. I tried focus first, but while open
el-tooltippoints the trigger'saria-describedbyat itself, so NVDA read every label twice ("Files, toggle button, pressed … Files"). Keyboard users get the focus ring, and screen reader users get the name.axe-core 4.13 (WCAG 2.0–2.2 A/AA rules) on the same states:
button-namein the find bar goes from 4 to 0,labelacross the seven Preferences pages goes from 56 to 0 (57 on Windows, which has one extra setting), andtarget-sizeon the keybindings page goes from 45 to 0. The remaining findings are pre-existing and out of scope here (see below).Screenshots
Windows 11, default light theme, reached with Tab. Before this change none of these controls could take keyboard focus, so there was no "before" state to capture.
One Dark, to show the ring follows the theme:
Type of change
Test plan
test/unit/specs/icon-button-a11y.spec.tsparses every renderer template and fails if a<button>/<el-button>without text has noaria-label, if anIconTooltipwraps a control labelled differently from the tooltip, or if it wraps a control that needsaria-expanded/aria-haspopup. It also checks the focus ring is at least 3:1 against the side bar, editor and floating surfaces in every theme. Ondevelopthe first check lists 12 unnamed buttons.test/e2e/issue-4997-icon-button-names.spec.tsdrives the built app: names and pressed state on the side bar, Enter/Space activating a tooltip-wrapped button, hover tooltip + Escape, no tooltip oraria-describedbyon keyboard focus, focus ring, Tab reaching New Tab and opening a tab, find bar names/state, window control names and order, and an accessible name for every visible control on all seven Preferences pages.search-prefill.spec.tsgets a stub for the new import.pnpm run lint,pnpm run typecheckand the unit suite pass on both machines. On Windows the new e2e spec passes in full (16/16), along withfind-replace,media-viewer,media-viewer-modalanddiagram-viewer. On macOS the window-controls case skips because there are no custom window controls there.developon the same machines: Windows fails the same 11 specs on both (353 passed on the branch, 341 ondevelop; the difference is the new spec). macOS fails 9 ondevelopand the same 9 plus three hover-tooltip cases on the branch, which pass on Windows (see the VoiceOver note below). On macOS:external-reload-undo(source-mode scrollTop) andissue-5394-image-resize-reload. On Windows:image-relative-path,issue-2245-window-menu-bar,issue-3020-second-instance-args,issue-3148-sidebar-delete-key,issue-5344-image-content-hash,search-prefill-from-selectionandsidebar-auto-reveal-528. Hover-tooltip specs (media-viewer,diagram-viewerand two of mine) also fail on my Mac only because VoiceOver is running there with "mouse pointer follows VoiceOver cursor", which moves the real pointer; they pass on Windows.source-toc-scrollandtitlebar-selection-word-countwere intermittent on my Mac on both branches. I didn't touch those areas.Notes for reviewers
IconTooltipkeeps the<button>in the caller's template, so the caller's scoped styles still reach it. Its comment documents the twoel-tooltipconstraints (Enter/Space and the ARIA attributes it overwrites). The find bar chevron and the app menu button are not wrapped for that reason..plain-buttoninindex.cssonly strips the browser's button chrome and adds the focus ring. Each component keeps its own sizing and colours.role="tree"/tablist), the side bar resize handle,<html lang>, pre-existing colour-contrast findings, Element Plus's unlabelled autocomplete wrapper, and Muya's floating toolbars (they need a keyboard path before naming them helps).By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.