From 74e81ceb869b6c0a275ec53e5d8f00022a576526 Mon Sep 17 00:00:00 2001 From: Ben Henning Date: Wed, 3 Dec 2025 15:11:53 -0800 Subject: [PATCH] feat: Add labels for Toolbox and Flyout. (#9483) ## The basics - [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change) ## The details ### Resolves Fixes #9464 ### Proposed Changes Adds ARIA labels for `Toolbox` and `Flyout` ('s `Workspace`) containers to complement their existing region labels. ### Reason for Changes In some cases certain screen readers (like NVDA) don't read out region labels. Previously, only the region labels provided context for currently being within the toolbox or flyout, so adding additional labels on the ARIA `tree` containers themselves ensures that these contexts are always read if the tree's context is read. This adds redundancy with the region output if both are read, but ChromeVox at least adds some delay between finishing the tree's context and beginning the region's context and this seems to mesh well together. The fully read context now feels like: "here's an item, it's the toolbox tree, and that tree is within the toolbox region." Even though both regions only contain a single tree it doesn't feel dimorphic. ### Test Coverage No new automated tests are needed for this experimental change. This has been manually tested with ChromeVox to demonstrate the dual tree + region output for both toolbox and flyout: [Screen recording 2025-11-26 2.52.22 PM.webm](https://github.com/user-attachments/assets/aa43ae81-9da6-4c79-b0fc-120146892aae) ### Documentation No new documentation is needed for this experimental change. ### Additional Information This was only tested on ChromeVox. --- core/toolbox/toolbox.ts | 5 +++++ core/workspace_svg.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/core/toolbox/toolbox.ts b/core/toolbox/toolbox.ts index e03b09a37..dd3c0db6b 100644 --- a/core/toolbox/toolbox.ts +++ b/core/toolbox/toolbox.ts @@ -226,6 +226,11 @@ export class Toolbox contentsContainer.style.flexDirection = 'row'; } aria.setRole(contentsContainer, aria.Role.TREE); + aria.setState( + contentsContainer, + aria.State.LABEL, + Msg['TOOLBOX_ARIA_LABEL'], + ); return contentsContainer; } diff --git a/core/workspace_svg.ts b/core/workspace_svg.ts index b919fa5c7..1f16f24c6 100644 --- a/core/workspace_svg.ts +++ b/core/workspace_svg.ts @@ -806,6 +806,7 @@ export class WorkspaceSvg if (this.isFlyout) { // Use the block canvas as the primary tree parent for flyout blocks. aria.setRole(this.svgBlockCanvas_, aria.Role.TREE); + aria.setState(this.svgBlockCanvas_, aria.State.LABEL, ariaLabel); } else { browserEvents.conditionalBind( this.svgGroup_,