From 27fe7644283cc2bd1072615a576a6551877748a9 Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Thu, 18 Sep 2025 14:27:41 -0700 Subject: [PATCH] fix: improve screenreader output for workspace comments (#9351) * fix: improve screenreader output for workspace comments * fix: run npm run messages to fully add new message * fix: remove useless bubble label * fix: use roledescription instead of description --- core/bubbles/bubble.ts | 1 - core/comments/collapse_comment_bar_button.ts | 4 +++- core/comments/comment_editor.ts | 1 - core/comments/comment_view.ts | 9 ++++++--- core/comments/delete_comment_bar_button.ts | 4 +++- msg/json/en.json | 3 ++- msg/json/qqq.json | 1 + msg/messages.js | 3 +++ 8 files changed, 18 insertions(+), 8 deletions(-) diff --git a/core/bubbles/bubble.ts b/core/bubbles/bubble.ts index 26ca2f40b..8a6bacac5 100644 --- a/core/bubbles/bubble.ts +++ b/core/bubbles/bubble.ts @@ -144,7 +144,6 @@ export abstract class Bubble implements IBubble, ISelectable, IFocusableNode { this.focusableElement = overriddenFocusableElement ?? this.svgRoot; this.focusableElement.setAttribute('id', this.id); aria.setRole(this.focusableElement, aria.Role.GROUP); - aria.setState(this.focusableElement, aria.State.LABEL, 'Bubble'); browserEvents.conditionalBind( this.background, diff --git a/core/comments/collapse_comment_bar_button.ts b/core/comments/collapse_comment_bar_button.ts index f653e8d53..ee4133aba 100644 --- a/core/comments/collapse_comment_bar_button.ts +++ b/core/comments/collapse_comment_bar_button.ts @@ -5,6 +5,7 @@ */ import * as browserEvents from '../browser_events.js'; +import {Msg} from '../msg.js'; import * as touch from '../touch.js'; import * as aria from '../utils/aria.js'; import * as dom from '../utils/dom.js'; @@ -57,6 +58,7 @@ export class CollapseCommentBarButton extends CommentBarButton { }, this.container, ); + this.initAria(); this.bindId = browserEvents.conditionalBind( this.icon, 'pointerdown', @@ -74,7 +76,7 @@ export class CollapseCommentBarButton extends CommentBarButton { override initAria(): void { aria.setRole(this.icon, aria.Role.BUTTON); - aria.setState(this.icon, aria.State.LABEL, 'DoNotDefine?'); + aria.setState(this.icon, aria.State.LABEL, Msg['COLLAPSE_COMMENT']); } /** diff --git a/core/comments/comment_editor.ts b/core/comments/comment_editor.ts index e1a4f5557..a5ce260a9 100644 --- a/core/comments/comment_editor.ts +++ b/core/comments/comment_editor.ts @@ -58,7 +58,6 @@ export class CommentEditor implements IFocusableNode { this.textArea.setAttribute('tabindex', '-1'); this.textArea.setAttribute('dir', this.workspace.RTL ? 'RTL' : 'LTR'); aria.setRole(this.textArea, aria.Role.TEXTBOX); - aria.setState(this.textArea, aria.State.LABEL, 'DoNotDefine?'); dom.addClass(this.textArea, 'blocklyCommentText'); dom.addClass(this.textArea, 'blocklyTextarea'); dom.addClass(this.textArea, 'blocklyText'); diff --git a/core/comments/comment_view.ts b/core/comments/comment_view.ts index 7258a7efb..a63971122 100644 --- a/core/comments/comment_view.ts +++ b/core/comments/comment_view.ts @@ -109,9 +109,6 @@ export class CommentView implements IRenderedElement { 'class': 'blocklyComment blocklyEditable blocklyDraggable', }); - aria.setRole(this.svgRoot, aria.Role.TEXTBOX); - aria.setState(this.svgRoot, aria.State.LABEL, 'DoNotOverride?'); - this.highlightRect = this.createHighlightRect(this.svgRoot); ({ @@ -127,6 +124,12 @@ export class CommentView implements IRenderedElement { this.resizeHandle = this.createResizeHandle(this.svgRoot, workspace); + aria.setRole(this.svgRoot, aria.Role.BUTTON); + if (this.commentEditor.id) { + aria.setState(this.svgRoot, aria.State.LABELLEDBY, this.commentEditor.id); + } + aria.setState(this.svgRoot, aria.State.ROLEDESCRIPTION, 'Comment'); + // TODO: Remove this comment before merging. // I think we want comments to exist on the same layer as blocks. workspace.getLayerManager()?.append(this, layers.BLOCK); diff --git a/core/comments/delete_comment_bar_button.ts b/core/comments/delete_comment_bar_button.ts index 16a1d5b80..f6096d175 100644 --- a/core/comments/delete_comment_bar_button.ts +++ b/core/comments/delete_comment_bar_button.ts @@ -6,6 +6,7 @@ import * as browserEvents from '../browser_events.js'; import {getFocusManager} from '../focus_manager.js'; +import {Msg} from '../msg.js'; import * as touch from '../touch.js'; import * as aria from '../utils/aria.js'; import * as dom from '../utils/dom.js'; @@ -57,6 +58,7 @@ export class DeleteCommentBarButton extends CommentBarButton { }, container, ); + this.initAria(); this.bindId = browserEvents.conditionalBind( this.icon, 'pointerdown', @@ -74,7 +76,7 @@ export class DeleteCommentBarButton extends CommentBarButton { override initAria(): void { aria.setRole(this.icon, aria.Role.BUTTON); - aria.setState(this.icon, aria.State.LABEL, 'DoNotDefine?'); + aria.setState(this.icon, aria.State.LABEL, Msg['REMOVE_COMMENT']); } /** diff --git a/msg/json/en.json b/msg/json/en.json index ec5862ae4..b517da800 100644 --- a/msg/json/en.json +++ b/msg/json/en.json @@ -1,7 +1,7 @@ { "@metadata": { "author": "Ellen Spertus ", - "lastupdated": "2025-09-08 16:26:57.642330", + "lastupdated": "2025-09-09 09:40:56.729862", "locale": "en", "messagedocumentation" : "qqq" }, @@ -12,6 +12,7 @@ "ADD_COMMENT": "Add Comment", "REMOVE_COMMENT": "Remove Comment", "DUPLICATE_COMMENT": "Duplicate Comment", + "COLLAPSE_COMMENT": "Collapse Comment", "EXTERNAL_INPUTS": "External Inputs", "INLINE_INPUTS": "Inline Inputs", "DELETE_BLOCK": "Delete Block", diff --git a/msg/json/qqq.json b/msg/json/qqq.json index 5e03efc41..69228de71 100644 --- a/msg/json/qqq.json +++ b/msg/json/qqq.json @@ -19,6 +19,7 @@ "ADD_COMMENT": "context menu - Add a descriptive comment to the selected block.", "REMOVE_COMMENT": "context menu - Remove the descriptive comment from the selected block.", "DUPLICATE_COMMENT": "context menu - Make a copy of the selected workspace comment.\n{{Identical|Duplicate}}", + "COLLAPSE_COMMENT": "context menu - Collapse the selected workspace comment.", "EXTERNAL_INPUTS": "context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]].\n\nThe opposite of {{msg-blockly|INLINE INPUTS}}.", "INLINE_INPUTS": "context menu - Change from 'internal' to 'external' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]].\n\nThe opposite of {{msg-blockly|EXTERNAL INPUTS}}.", "DELETE_BLOCK": "context menu - Permanently delete the selected block.", diff --git a/msg/messages.js b/msg/messages.js index 1095ae057..28ef830c4 100644 --- a/msg/messages.js +++ b/msg/messages.js @@ -85,6 +85,9 @@ Blockly.Msg.REMOVE_COMMENT = 'Remove Comment'; /// context menu - Make a copy of the selected workspace comment.\n{{Identical|Duplicate}} Blockly.Msg.DUPLICATE_COMMENT = 'Duplicate Comment'; /** @type {string} */ +/// context menu - Collapse the selected workspace comment. +Blockly.Msg.COLLAPSE_COMMENT = 'Collapse Comment'; +/** @type {string} */ /// context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]].\n\nThe opposite of {{msg-blockly|INLINE INPUTS}}. Blockly.Msg.EXTERNAL_INPUTS = 'External Inputs'; /** @type {string} */