fix: Fix Escape in toolboxes and flyouts

This commit is contained in:
Aaron Dodson
2026-04-27 09:17:20 -07:00
parent c211a8955b
commit 688a014e59
3 changed files with 76 additions and 0 deletions
+11
View File
@@ -289,6 +289,17 @@ export abstract class Flyout
.getThemeManager()
.subscribe(this.svgBackground_, 'flyoutOpacity', 'fill-opacity');
this.svgGroup_.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Escape') {
getFocusManager().focusTree(this.targetWorkspace);
if (!this.targetWorkspace.isMutator) {
this.autoHide(false);
}
e.preventDefault();
e.stopPropagation();
}
});
return this.svgGroup_;
}
+4
View File
@@ -311,6 +311,10 @@ export class Toolbox
case 'ArrowRight':
handled = this.toggleSelectedItem(true);
break;
case 'Escape':
getFocusManager().focusTree(this.getWorkspace());
handled = true;
break;
}
if (handled) {
@@ -89,27 +89,88 @@ suite('Keyboard Shortcut Items', function () {
'hideChaff',
);
});
test('Simple', function () {
this.injectionDiv.dispatchEvent(this.event);
sinon.assert.calledOnce(this.hideChaffSpy);
});
runReadOnlyTest(createKeyDownEvent(Blockly.utils.KeyCodes.ESC));
test('Not called when focus is on an HTML input', function () {
const event = createKeyDownEvent(Blockly.utils.KeyCodes.ESC);
const input = document.createElement('textarea');
input.dispatchEvent(event);
sinon.assert.notCalled(this.hideChaffSpy);
});
test('Not called on hidden workspaces', function () {
this.workspace.visible = false;
this.injectionDiv.dispatchEvent(this.event);
sinon.assert.notCalled(this.hideChaffSpy);
});
test('Called when connection is focused', function () {
setSelectedConnection(this.workspace);
this.injectionDiv.dispatchEvent(this.event);
sinon.assert.calledOnce(this.hideChaffSpy);
});
test('In the toolbox focuses the workspace', function () {
Blockly.getFocusManager().focusNode(
this.workspace.getToolbox().getToolboxItems()[0],
);
assert.equal(
Blockly.getFocusManager().getFocusedTree(),
this.workspace.getToolbox(),
);
const event = new KeyboardEvent('keydown', {
keyCode: Blockly.utils.KeyCodes.ESC,
key: 'Escape',
});
this.workspace.getToolbox().contentsDiv_.dispatchEvent(event);
assert.equal(Blockly.getFocusManager().getFocusedTree(), this.workspace);
});
test('In the flyout focues the workspace', function () {
this.injectionDiv.dispatchEvent(
createKeyDownEvent(Blockly.utils.KeyCodes.T),
);
this.injectionDiv.dispatchEvent(
createKeyDownEvent(Blockly.utils.KeyCodes.RIGHT),
);
assert.equal(
Blockly.getFocusManager().getFocusedTree(),
this.workspace.getFlyout().getWorkspace(),
);
const event = new KeyboardEvent('keydown', {
keyCode: Blockly.utils.KeyCodes.ESC,
key: 'Escape',
});
this.workspace.getFlyout().svgGroup_.dispatchEvent(event);
assert.equal(Blockly.getFocusManager().getFocusedTree(), this.workspace);
});
test('In a mutator flyout focuses the mutator workspace', async function () {
const block = this.workspace.newBlock('controls_if');
block.initSvg();
block.render();
const mutatorIcon = block.getIcon(Blockly.icons.MutatorIcon.TYPE);
await mutatorIcon.setBubbleVisible(true);
const bubble = mutatorIcon.getBubble();
Blockly.getFocusManager().focusTree(bubble.getWorkspace().getFlyout().getWorkspace());
const event = new KeyboardEvent('keydown', {
keyCode: Blockly.utils.KeyCodes.ESC,
key: 'Escape',
});
bubble.getWorkspace().getFlyout().svgGroup_.dispatchEvent(event);
assert.equal(
Blockly.getFocusManager().getFocusedTree(),
bubble.getWorkspace(),
);
});
});
suite('Delete', function () {