diff --git a/webapp/src/components/KeyboardControlsHelp.tsx b/webapp/src/components/KeyboardControlsHelp.tsx index 038078d8db0e..e90c4e0c7dd9 100644 --- a/webapp/src/components/KeyboardControlsHelp.tsx +++ b/webapp/src/components/KeyboardControlsHelp.tsx @@ -1,6 +1,7 @@ import * as React from "react"; import * as Blockly from "blockly"; -import { getShortcutKeysShortAll, LIST_SHORTCUTS_SHORTCUT } from "../shortcut_formatting"; +import { CONTROL_KEY_SHORT, getShortcutKeysShortAll, LIST_SHORTCUTS_SHORTCUT } from "../shortcut_formatting"; +import { jsxLF } from "../../../react-common/components/util"; const names = Blockly.ShortcutItems.names; const isMacPlatform = pxt.BrowserUtils.isMac(); @@ -10,7 +11,7 @@ const KeyboardControlsHelp = () => { React.useEffect(() => { ref.current?.focus() }, []); - const ctrl = lf("{id:keyboard symbol}Ctrl"); + const ctrl = CONTROL_KEY_SHORT; const cmd = isMacPlatform ? "⌘" : ctrl; const orAsJoiner = lf("or") const enterOrSpace = { shortcuts: getShortcutKeysShortAll(names.PERFORM_ACTION), joiner: orAsJoiner} @@ -21,9 +22,6 @@ const KeyboardControlsHelp = () => { - -

{lf("Additional audio cues and navigation aids for screen reader users")}

-

{lf("Then press an area's number, or Tab to it and press Enter")}

@@ -37,7 +35,7 @@ const KeyboardControlsHelp = () => { - + {pxt.canDownload() && @@ -45,6 +43,9 @@ const KeyboardControlsHelp = () => { {pxt.appTarget.simulator && } + +

{lf("Additional audio cues and navigation aids for screen reader users")}

+

{lf("Toolbox")}

@@ -78,7 +79,7 @@ const KeyboardControlsHelp = () => { - {lf("Hold {0} and press arrow keys", cmd)} + {jsxLF(lf("Hold {0} and press arrow keys"), )} @@ -177,6 +178,10 @@ const Key = ({ value }: { value: string }) => { aria = lf("Option"); break; } + case CONTROL_KEY_SHORT: { + aria = Blockly.Msg['CONTROL_KEY']; + break; + } } return {value} } diff --git a/webapp/src/shortcut_formatting.ts b/webapp/src/shortcut_formatting.ts index dd0d5901f503..7d3669c6c4b3 100644 --- a/webapp/src/shortcut_formatting.ts +++ b/webapp/src/shortcut_formatting.ts @@ -2,6 +2,8 @@ import * as Blockly from 'blockly'; const isMacPlatform = pxt.BrowserUtils.isMac(); +export const CONTROL_KEY_SHORT = lf("{id:keyboard symbol}Ctrl"); + /** * Name of the shortcut that opens the help dialog. Registered in blocks.tsx * initKeyboardControls. The literal string is also hardcoded by Blockly core's @@ -47,7 +49,7 @@ const longModifierNames: Record = { }; const shortModifierNames: Record = { - 'Control': Blockly.Msg['CONTROL_KEY'], + 'Control': CONTROL_KEY_SHORT, 'Meta': '⌘', 'Alt': isMacPlatform ? '⌥' : Blockly.Msg['ALT_KEY'], }; @@ -149,7 +151,8 @@ function getKeyName(keyCode: number): string { * * Mirrors Blockly's internal getShortcutKeys (core/utils/shortcut_formatting.ts). * Kept as a local copy because Blockly doesn't expose this on its public API - * surface; the algorithm should track Blockly's version. + * surface; the algorithm tracks Blockly's version with an exception to avoid + * the menu key for the context menu shortcut (not present on all keyboards). * * @param shortcutName The action name, e.g. "cut". * @param modifierNames The names to use for the Meta/Control/Alt modifiers. @@ -186,12 +189,13 @@ function getShortcutKeys( // If there are modifiers return only one shortcut on the assumption they are // intended for different platforms. Otherwise assume they are alternatives. + // Skips a bare key here for the menu key case. const hasModifiers = currentPlatform.some((shortcut) => - shortcut.some( - (key) => "Meta" === key || "Alt" === key || "Control" === key, - ), + shortcut.some(isModifierName), ); - const chosen = hasModifiers ? [currentPlatform[0]] : currentPlatform; + const chosen = hasModifiers + ? [currentPlatform.find((shortcut) => shortcut.some(isModifierName)) ?? currentPlatform[0]] + : currentPlatform; return chosen.map((shortcut) => shortcut .map((maybeNumeric) => @@ -217,3 +221,8 @@ function modifierOrder(key: string): number { // Regular keys at the end. return order === -1 ? Number.MAX_VALUE : order; } + +/** Whether a serialized key part is one of the (non-Shift) modifier names. */ +function isModifierName(key: string): boolean { + return key === "Meta" || key === "Alt" || key === "Control"; +}