diff --git a/core/layer_manager.ts b/core/layer_manager.ts index a7cb579348f..1d5afdd74e9 100644 --- a/core/layer_manager.ts +++ b/core/layer_manager.ts @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {getFocusManager} from './focus_manager.js'; +import type {IFocusableNode} from './interfaces/i_focusable_node.js'; import {IRenderedElement} from './interfaces/i_rendered_element.js'; import * as layerNums from './layers.js'; import {Coordinate} from './utils/coordinate.js'; @@ -99,8 +101,12 @@ export class LayerManager { * * @internal */ - moveToDragLayer(elem: IRenderedElement) { + moveToDragLayer(elem: IRenderedElement & IFocusableNode) { this.dragLayer?.appendChild(elem.getSvgRoot()); + + // Since moving the element to the drag layer will cause it to lose focus, + // ensure it regains focus (to ensure proper highlights & sent events). + getFocusManager().focusNode(elem); } /** @@ -108,8 +114,12 @@ export class LayerManager { * * @internal */ - moveOffDragLayer(elem: IRenderedElement, layerNum: number) { + moveOffDragLayer(elem: IRenderedElement & IFocusableNode, layerNum: number) { this.append(elem, layerNum); + + // Since moving the element off the drag layer will cause it to lose focus, + // ensure it regains focus (to ensure proper highlights & sent events). + getFocusManager().focusNode(elem); } /** diff --git a/core/renderers/zelos/path_object.ts b/core/renderers/zelos/path_object.ts index f40426483a7..3c304fd6bf8 100644 --- a/core/renderers/zelos/path_object.ts +++ b/core/renderers/zelos/path_object.ts @@ -8,6 +8,7 @@ import type {BlockSvg} from '../../block_svg.js'; import type {Connection} from '../../connection.js'; +import {FocusManager} from '../../focus_manager.js'; import type {BlockStyle} from '../../theme.js'; import * as dom from '../../utils/dom.js'; import {Svg} from '../../utils/svg.js'; @@ -91,6 +92,17 @@ export class PathObject extends BasePathObject { if (!this.svgPathSelected) { this.svgPathSelected = this.svgPath.cloneNode(true) as SVGElement; this.svgPathSelected.classList.add('blocklyPathSelected'); + // Ensure focus-specific properties don't overlap with the block's path. + dom.removeClass( + this.svgPathSelected, + FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME, + ); + dom.removeClass( + this.svgPathSelected, + FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME, + ); + this.svgPathSelected.removeAttribute('tabindex'); + this.svgPathSelected.removeAttribute('id'); this.svgRoot.appendChild(this.svgPathSelected); } } else { diff --git a/tests/mocha/layering_test.js b/tests/mocha/layering_test.js index efc3ef3d632..1ef0ee6973d 100644 --- a/tests/mocha/layering_test.js +++ b/tests/mocha/layering_test.js @@ -24,6 +24,15 @@ suite('Layering', function () { const g = Blockly.utils.dom.createSvgElement('g', {}); return { getSvgRoot: () => g, + getFocusableElement: () => { + throw new Error('Unsupported.'); + }, + getFocusableTree: () => { + throw new Error('Unsupported.'); + }, + onNodeFocus: () => {}, + onNodeBlur: () => {}, + canBeFocused: () => false, }; }