From a8d98c7cf2ad8dc0581668674c991b99cb27b853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20Monda?= Date: Sun, 16 Aug 2026 17:09:39 +0200 Subject: [PATCH 1/3] fix: make keymap SVG keys findable with VoiceOver Name keys by physical QWERTY position plus current mapping, and hide off-screen layers and the remap overlay from the accessibility tree so icon-only and unmapped keys remain searchable. Co-authored-by: Cursor --- .../slider/keyboard-slider.component.html | 4 + .../components/popover/popover.component.html | 2 +- .../svg/keyboard/svg-keyboard.component.html | 1 + .../svg-icon-text-key.component.html | 1 + .../svg-keyboard-key.component.html | 4 + .../svg-keyboard-key.component.scss | 8 + .../svg-keyboard-key.component.ts | 85 +++------ .../svg-keystroke-key.component.html | 6 +- .../svg-mouse-click-key.html | 2 +- .../svg-mouse-move-key.html | 4 +- .../svg-mouse-scroll-key.html | 4 +- .../svg-mouse-speed-key.html | 2 +- .../svg-single-icon-key.component.html | 1 + .../svg-switch-keymap-key.component.html | 1 + .../svg-text-icon-key.component.html | 1 + .../svg/module/svg-module.component.html | 3 + .../svg/module/svg-module.component.ts | 44 +++-- .../svg/wrap/svg-keyboard-wrap.component.html | 12 +- .../util/build-key-accessible-label.test.ts | 175 ++++++++++++++++++ .../app/util/build-key-accessible-label.ts | 112 +++++++++++ 20 files changed, 388 insertions(+), 84 deletions(-) create mode 100644 packages/uhk-web/src/app/util/build-key-accessible-label.test.ts create mode 100644 packages/uhk-web/src/app/util/build-key-accessible-label.ts diff --git a/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.html b/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.html index 58e0c1d6a49..039f9867cbd 100644 --- a/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.html +++ b/packages/uhk-web/src/app/components/keyboard/slider/keyboard-slider.component.html @@ -1,5 +1,7 @@ - + diff --git a/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.html b/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.html index 7fc73c11797..92595740b32 100644 --- a/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.html +++ b/packages/uhk-web/src/app/components/svg/keyboard/svg-keyboard.component.html @@ -14,6 +14,7 @@ [capturingEnabled]="capturingEnabled" [attr.transform]="module.attributes.transform" [keyActions]="getKeyActions(module.id)" + [moduleId]="module.id" [moduleNavCircle]="module.moduleNavCircle" [moduleNavPath]="module.moduleNavPath" [selectedKey]="selectedKey" diff --git a/packages/uhk-web/src/app/components/svg/keys/svg-icon-text-key/svg-icon-text-key.component.html b/packages/uhk-web/src/app/components/svg/keys/svg-icon-text-key/svg-icon-text-key.component.html index 59f52a96254..3927b1ac0db 100644 --- a/packages/uhk-web/src/app/components/svg/keys/svg-icon-text-key/svg-icon-text-key.component.html +++ b/packages/uhk-web/src/app/components/svg/keys/svg-icon-text-key/svg-icon-text-key.component.html @@ -3,6 +3,7 @@ [attr.height]="useHeight" [attr.x]="useX" [attr.y]="useY" + aria-hidden="true" stroke-width="0" > diff --git a/packages/uhk-web/src/app/components/svg/keys/svg-keyboard-key/svg-keyboard-key.component.html b/packages/uhk-web/src/app/components/svg/keys/svg-keyboard-key/svg-keyboard-key.component.html index 872cd701b4d..4607b90f315 100644 --- a/packages/uhk-web/src/app/components/svg/keys/svg-keyboard-key/svg-keyboard-key.component.html +++ b/packages/uhk-web/src/app/components/svg/keys/svg-keyboard-key/svg-keyboard-key.component.html @@ -1,3 +1,4 @@ +{{ accessibleLabel }} +{{ accessibleLabel }} (); + @Input() moduleId = 0; @Input() lastEdited: boolean; @Input() lastEditedKey: LastEditedKey; @@ -364,7 +370,11 @@ export class SvgKeyboardKeyComponent implements OnChanges, OnDestroy { } ngOnChanges(changes: SimpleChanges) { - if (changes['keyAction']) { + if (changes['keyAction'] + || changes['defaultUserConfiguration'] + || changes['keyId'] + || changes['macroMap'] + || changes['moduleId']) { this.setLabels(); } @@ -472,9 +482,9 @@ export class SvgKeyboardKeyComponent implements OnChanges, OnDestroy { this.labelType = LabelTypes.OneLineText; this.labelSource = undefined; this.secondaryText = undefined; - this.accessibleLabel = 'Unassigned key'; if (!this.keyAction) { + this.updateAccessibleLabel(); return; } @@ -630,7 +640,7 @@ export class SvgKeyboardKeyComponent implements OnChanges, OnDestroy { this.labelSource = undefined; } - this.accessibleLabel = this.buildAccessibleLabel(); + this.updateAccessibleLabel(); } private blinkSvgRec(): void { @@ -685,59 +695,20 @@ export class SvgKeyboardKeyComponent implements OnChanges, OnDestroy { } } - private buildAccessibleLabel(): string { - if (!this.keyAction) { - return 'Unassigned key'; - } - - if (this.keyAction instanceof KeystrokeAction) { - const parts: string[] = []; - - if (this.keyAction.hasActiveModifier()) { - parts.push(this.keyAction.getModifierList().join(' + ')); - } - - if (this.keyAction.hasScancode()) { - parts.push(this.mapper.scanCodeToText(this.keyAction.scancode, this.keyAction.type).join(' ')); - } - - if (parts.length === 0) { - parts.push('Keystroke'); - } - - if (this.keyAction.hasSecondaryRoleAction()) { - parts.push(`secondary role ${this.mapper.getSecondaryRoleText(this.keyAction.secondaryRoleAction)}`); - } - - return parts.join(', '); - } - - if (this.keyAction instanceof SwitchLayerAction) { - const layerName = this.layerOptionMap.get(this.keyAction.layer)?.name || 'unknown'; - return `Switch to ${layerName} layer`; - } - - if (this.keyAction instanceof SwitchKeymapAction) { - return `Switch to keymap ${this.keyAction.keymapAbbreviation}`; - } - - if (this.keyAction instanceof PlayMacroAction) { - const macroName = this.macroMap.get(this.keyAction.macroId)?.name; - return macroName ? `Play macro ${macroName}` : 'Play macro'; - } - - if (this.keyAction instanceof MouseAction) { - return 'Mouse action'; - } - - if (this.keyAction instanceof ConnectionsAction) { - return 'Host connection action'; - } - - if (this.keyAction instanceof OtherAction) { - return 'Other action'; - } + private updateAccessibleLabel(): void { + const physicalKeyLabel = getDefaultQwertyKeyLabel({ + defaultUserConfiguration: this.defaultUserConfiguration, + keyId: this.keyId, + mapper: this.mapper, + moduleId: this.moduleId, + }); - return 'Assigned key action'; + this.accessibleLabel = buildKeyAccessibleLabel({ + keyAction: this.keyAction, + layerOptionMap: this.layerOptionMap, + macroMap: this.macroMap, + mapper: this.mapper, + physicalKeyLabel, + }); } } diff --git a/packages/uhk-web/src/app/components/svg/keys/svg-keystroke-key/svg-keystroke-key.component.html b/packages/uhk-web/src/app/components/svg/keys/svg-keystroke-key/svg-keystroke-key.component.html index 5000ce125ea..deb8bd1eba2 100644 --- a/packages/uhk-web/src/app/components/svg/keys/svg-keystroke-key/svg-keystroke-key.component.html +++ b/packages/uhk-web/src/app/components/svg/keys/svg-keystroke-key/svg-keystroke-key.component.html @@ -41,7 +41,7 @@ [attr.y]="modifierContainer.y" preserveAspectRatio="none"> - + @@ -49,12 +49,12 @@ - + A - + S diff --git a/packages/uhk-web/src/app/components/svg/keys/svg-mouse-click-key/svg-mouse-click-key.html b/packages/uhk-web/src/app/components/svg/keys/svg-mouse-click-key/svg-mouse-click-key.html index 27dcab28b08..e98281ff59e 100644 --- a/packages/uhk-web/src/app/components/svg/keys/svg-mouse-click-key/svg-mouse-click-key.html +++ b/packages/uhk-web/src/app/components/svg/keys/svg-mouse-click-key/svg-mouse-click-key.html @@ -1,4 +1,4 @@ - + + Move - + diff --git a/packages/uhk-web/src/app/components/svg/keys/svg-mouse-scroll-key/svg-mouse-scroll-key.html b/packages/uhk-web/src/app/components/svg/keys/svg-mouse-scroll-key/svg-mouse-scroll-key.html index db0896bd698..56b22985c5b 100644 --- a/packages/uhk-web/src/app/components/svg/keys/svg-mouse-scroll-key/svg-mouse-scroll-key.html +++ b/packages/uhk-web/src/app/components/svg/keys/svg-mouse-scroll-key/svg-mouse-scroll-key.html @@ -1,4 +1,4 @@ - + Scroll - + diff --git a/packages/uhk-web/src/app/components/svg/keys/svg-mouse-speed-key/svg-mouse-speed-key.html b/packages/uhk-web/src/app/components/svg/keys/svg-mouse-speed-key/svg-mouse-speed-key.html index bb8542641cd..651a0db1ac5 100644 --- a/packages/uhk-web/src/app/components/svg/keys/svg-mouse-speed-key/svg-mouse-speed-key.html +++ b/packages/uhk-web/src/app/components/svg/keys/svg-mouse-speed-key/svg-mouse-speed-key.html @@ -1,4 +1,4 @@ - +