From c185d0fa9b163572b37e2189b54aaa3c3231bb90 Mon Sep 17 00:00:00 2001 From: lizschwab Date: Mon, 11 May 2026 09:03:26 -0700 Subject: [PATCH] feat!: Added additional keyboard shortcuts for context menu (#9845) * feat: Added additional keyboard shortcuts for context menu * formatting --- packages/blockly/core/shortcut_items.ts | 9 +- .../tests/mocha/shortcut_items_test.js | 116 +++++++++++++++++- 2 files changed, 119 insertions(+), 6 deletions(-) diff --git a/packages/blockly/core/shortcut_items.ts b/packages/blockly/core/shortcut_items.ts index 1d19fc110..1aa800a20 100644 --- a/packages/blockly/core/shortcut_items.ts +++ b/packages/blockly/core/shortcut_items.ts @@ -568,7 +568,8 @@ export function registerMovementShortcuts() { } /** - * Keyboard shortcut to show the context menu on ctrl/cmd+Enter. + * Keyboard shortcut to show the context menu on ctrl/cmd+Enter, shift+F10, and + * the menu key. */ export function registerShowContextMenu() { const ctrlEnter = ShortcutRegistry.registry.createSerializedKey( @@ -576,6 +577,10 @@ export function registerShowContextMenu() { [KeyCodes.CTRL_CMD], ); + const shiftF10 = ShortcutRegistry.registry.createSerializedKey(KeyCodes.F10, [ + KeyCodes.SHIFT, + ]); + const contextMenuShortcut: KeyboardShortcut = { name: names.MENU, preconditionFn: (workspace) => { @@ -592,7 +597,7 @@ export function registerShowContextMenu() { } return false; }, - keyCodes: [ctrlEnter], + keyCodes: [ctrlEnter, shiftF10, KeyCodes.CONTEXT_MENU], displayText: () => Msg['SHORTCUTS_SHOW_CONTEXT_MENU'], }; ShortcutRegistry.registry.register(contextMenuShortcut); diff --git a/packages/blockly/tests/mocha/shortcut_items_test.js b/packages/blockly/tests/mocha/shortcut_items_test.js index f03e048c1..27329b67b 100644 --- a/packages/blockly/tests/mocha/shortcut_items_test.js +++ b/packages/blockly/tests/mocha/shortcut_items_test.js @@ -522,13 +522,21 @@ suite('Keyboard Shortcut Items', function () { ); }); - suite('Show context menu (Ctrl/Cmd+Enter)', function () { + suite('Show context menu', function () { const contextMenuKeyEvent = createKeyDownEvent( Blockly.utils.KeyCodes.ENTER, [Blockly.utils.KeyCodes.CTRL_CMD], ); - test('Displays context menu on a block using the keyboard shortcut', function () { + const shiftF10KeyEvent = createKeyDownEvent(Blockly.utils.KeyCodes.F10, [ + Blockly.utils.KeyCodes.SHIFT, + ]); + + const menuKeyEvent = createKeyDownEvent( + Blockly.utils.KeyCodes.CONTEXT_MENU, + ); + + test('Displays context menu on a block using Ctrl/Cmd+Enter', function () { const block = setSelectedBlock(this.workspace); this.injectionDiv.dispatchEvent(contextMenuKeyEvent); @@ -545,7 +553,7 @@ suite('Keyboard Shortcut Items', function () { } }); - test('Displays context menu on the workspace using the keyboard shortcut', function () { + test('Displays context menu on the workspace using Ctrl/Cmd+Enter', function () { Blockly.getFocusManager().focusNode(this.workspace); this.injectionDiv.dispatchEvent(contextMenuKeyEvent); @@ -561,7 +569,7 @@ suite('Keyboard Shortcut Items', function () { } }); - test('Displays context menu on a workspace comment using the keyboard shortcut', function () { + test('Displays context menu on a workspace comment using Ctrl/Cmd+Enter', function () { Blockly.ContextMenuItems.registerCommentOptions(); const comment = setSelectedComment(this.workspace); this.injectionDiv.dispatchEvent(contextMenuKeyEvent); @@ -578,6 +586,106 @@ suite('Keyboard Shortcut Items', function () { } }); + test('Displays context menu on a block using Shift+F10', function () { + const block = setSelectedBlock(this.workspace); + this.injectionDiv.dispatchEvent(shiftF10KeyEvent); + + const menu = Blockly.ContextMenu.getMenu(); + assert.instanceOf(menu, Blockly.Menu, 'Context menu should be shown'); + + const menuOptions = + Blockly.ContextMenuRegistry.registry.getContextMenuOptions( + {block, focusedNode: block}, + shiftF10KeyEvent, + ); + for (const option of menuOptions) { + assert.include(menu.getElement().textContent, option.text); + } + }); + + test('Displays context menu on the workspace using Shift+F10', function () { + Blockly.getFocusManager().focusNode(this.workspace); + this.injectionDiv.dispatchEvent(shiftF10KeyEvent); + + const menu = Blockly.ContextMenu.getMenu(); + assert.instanceOf(menu, Blockly.Menu, 'Context menu should be shown'); + const menuOptions = + Blockly.ContextMenuRegistry.registry.getContextMenuOptions( + {workspace: this.workspace, focusedNode: this.workspace}, + shiftF10KeyEvent, + ); + for (const option of menuOptions) { + assert.include(menu.getElement().textContent, option.text); + } + }); + + test('Displays context menu on a workspace comment using Shift+F10', function () { + Blockly.ContextMenuItems.registerCommentOptions(); + const comment = setSelectedComment(this.workspace); + this.injectionDiv.dispatchEvent(shiftF10KeyEvent); + + const menu = Blockly.ContextMenu.getMenu(); + assert.instanceOf(menu, Blockly.Menu, 'Context menu should be shown'); + const menuOptions = + Blockly.ContextMenuRegistry.registry.getContextMenuOptions( + {comment, focusedNode: comment}, + shiftF10KeyEvent, + ); + for (const option of menuOptions) { + assert.include(menu.getElement().textContent, option.text); + } + }); + + test('Displays context menu on a block using the menu button', function () { + const block = setSelectedBlock(this.workspace); + this.injectionDiv.dispatchEvent(menuKeyEvent); + + const menu = Blockly.ContextMenu.getMenu(); + assert.instanceOf(menu, Blockly.Menu, 'Context menu should be shown'); + + const menuOptions = + Blockly.ContextMenuRegistry.registry.getContextMenuOptions( + {block, focusedNode: block}, + menuKeyEvent, + ); + for (const option of menuOptions) { + assert.include(menu.getElement().textContent, option.text); + } + }); + + test('Displays context menu on the workspace using the menu button', function () { + Blockly.getFocusManager().focusNode(this.workspace); + this.injectionDiv.dispatchEvent(menuKeyEvent); + + const menu = Blockly.ContextMenu.getMenu(); + assert.instanceOf(menu, Blockly.Menu, 'Context menu should be shown'); + const menuOptions = + Blockly.ContextMenuRegistry.registry.getContextMenuOptions( + {workspace: this.workspace, focusedNode: this.workspace}, + menuKeyEvent, + ); + for (const option of menuOptions) { + assert.include(menu.getElement().textContent, option.text); + } + }); + + test('Displays context menu on a workspace comment using the menu button', function () { + Blockly.ContextMenuItems.registerCommentOptions(); + const comment = setSelectedComment(this.workspace); + this.injectionDiv.dispatchEvent(menuKeyEvent); + + const menu = Blockly.ContextMenu.getMenu(); + assert.instanceOf(menu, Blockly.Menu, 'Context menu should be shown'); + const menuOptions = + Blockly.ContextMenuRegistry.registry.getContextMenuOptions( + {comment, focusedNode: comment}, + menuKeyEvent, + ); + for (const option of menuOptions) { + assert.include(menu.getElement().textContent, option.text); + } + }); + test('First menu item is highlighted when context menu is shown via keyboard shortcut', function () { setSelectedBlock(this.workspace); this.injectionDiv.dispatchEvent(contextMenuKeyEvent);