From a61222f7279096d98c33bb2b5bb6830207710df0 Mon Sep 17 00:00:00 2001 From: lizschwab Date: Fri, 10 Apr 2026 14:40:42 -0700 Subject: [PATCH] fix: Add default aria role to svg and group elements (#9697) * fix: Add default aria role to svg and group elements * addressed pr feedback --- packages/blockly/core/utils/dom.ts | 14 ++++++- packages/blockly/tests/mocha/utils_test.js | 45 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/packages/blockly/core/utils/dom.ts b/packages/blockly/core/utils/dom.ts index 408798415..37bccb578 100644 --- a/packages/blockly/core/utils/dom.ts +++ b/packages/blockly/core/utils/dom.ts @@ -6,7 +6,8 @@ // Former goog.module ID: Blockly.utils.dom -import type {Svg} from './svg.js'; +import * as aria from './aria.js'; +import {Svg} from './svg.js'; /** * Required name space for SVG elements. @@ -56,6 +57,17 @@ export function createSvgElement( opt_parent?: Element | null, ): T { const e = document.createElementNS(SVG_NS, `${name}`) as T; + /** + * For svg and group (g) elements, we set the role to generic so that they are ignored by assistive technologies. + */ + if ( + name === Svg.SVG.toString() || + name === Svg.G.toString() || + e.tagName === Svg.SVG.toString() || + e.tagName === Svg.G.toString() + ) { + aria.setRole(e, aria.Role.GENERIC); + } for (const key in attrs) { e.setAttribute(key, `${attrs[key]}`); } diff --git a/packages/blockly/tests/mocha/utils_test.js b/packages/blockly/tests/mocha/utils_test.js index accf164b7..da6eac7ce 100644 --- a/packages/blockly/tests/mocha/utils_test.js +++ b/packages/blockly/tests/mocha/utils_test.js @@ -433,6 +433,51 @@ suite('Utils', function () { Blockly.utils.dom.removeClass(p, 'zero'); assert.equal(p.className, '', 'Removing "zero"'); }); + + suite('createSvgElement', function () { + test('svg elements of type g have the generic role by default', function () { + const svgG = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.G, + {}, + ); + const g = Blockly.utils.dom.createSvgElement('g', {}); + assert.equal(svgG.getAttribute('role'), 'generic'); + assert.equal(g.getAttribute('role'), 'generic'); + }); + test('svg elements of type svg have the generic role by default', function () { + const svgSvg = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.SVG, + {}, + ); + const svg = Blockly.utils.dom.createSvgElement('svg', {}); + assert.equal(svgSvg.getAttribute('role'), 'generic'); + assert.equal(svg.getAttribute('role'), 'generic'); + }); + test('svg elements of type g reflect the role passed in when created', function () { + const svgG = Blockly.utils.dom.createSvgElement(Blockly.utils.Svg.G, { + role: 'button', + }); + const g = Blockly.utils.dom.createSvgElement('g', {role: 'button'}); + assert.equal(svgG.getAttribute('role'), 'button'); + assert.equal(g.getAttribute('role'), 'button'); + }); + test('svg elements of type svg reflect the role passed in when created', function () { + const svgSvg = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.SVG, + {role: 'button'}, + ); + const svg = Blockly.utils.dom.createSvgElement('svg', {role: 'button'}); + assert.equal(svgSvg.getAttribute('role'), 'button'); + assert.equal(svg.getAttribute('role'), 'button'); + }); + test('other svg elements do not default to generic role', function () { + const textElement = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.TEXT, + {}, + ); + assert.equal(textElement.getAttribute('role'), null); + }); + }); }); suite('String', function () {