mirror of
https://github.com/google/blockly.git
synced 2026-04-26 07:00:23 +02:00
feat: Added keyboard shortcut for displaying tooltip (#9755)
* feat: Added keyboard shortcut for displaying tooltip * fix for tooltips not appearing near the focused block
This commit is contained in:
@@ -23,6 +23,7 @@ import {Direction, KeyboardMover} from './keyboard_nav/keyboard_mover.js';
|
||||
import {keyboardNavigationController} from './keyboard_navigation_controller.js';
|
||||
import {Msg} from './msg.js';
|
||||
import {KeyboardShortcut, ShortcutRegistry} from './shortcut_registry.js';
|
||||
import * as Tooltip from './tooltip.js';
|
||||
import {aria} from './utils.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import {KeyCodes} from './utils/keycodes.js';
|
||||
@@ -64,6 +65,7 @@ export enum names {
|
||||
PERFORM_ACTION = 'perform_action',
|
||||
DUPLICATE = 'duplicate',
|
||||
CLEANUP = 'cleanup',
|
||||
SHOW_TOOLTIP = 'show_tooltip',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -973,6 +975,32 @@ export function registerCleanup() {
|
||||
ShortcutRegistry.registry.register(cleanupShortcut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers keyboard shortcut to display the tooltip for the focused element.
|
||||
*/
|
||||
export function registerShowTooltip() {
|
||||
const ctrlJ = ShortcutRegistry.registry.createSerializedKey(KeyCodes.J, [
|
||||
KeyCodes.CTRL_CMD,
|
||||
]);
|
||||
|
||||
const showTooltip: KeyboardShortcut = {
|
||||
name: names.SHOW_TOOLTIP,
|
||||
preconditionFn: (workspace) => !workspace.isDragging(),
|
||||
callback: (workspace) => {
|
||||
const target = getFocusManager().getFocusedNode();
|
||||
if (target !== null) {
|
||||
keyboardNavigationController.setIsActive(true);
|
||||
Tooltip.display(target, workspace);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
keyCodes: [ctrlJ],
|
||||
allowCollision: true,
|
||||
displayText: () => Msg['SHORTCUTS_SHOW_TOOLTIP'],
|
||||
};
|
||||
ShortcutRegistry.registry.register(showTooltip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all default keyboard shortcut item. This should be called once per
|
||||
* instance of KeyboardShortcutRegistry.
|
||||
@@ -1004,6 +1032,7 @@ export function registerKeyboardNavigationShortcuts() {
|
||||
registerPerformAction();
|
||||
registerDuplicate();
|
||||
registerCleanup();
|
||||
registerShowTooltip();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import * as common from './common.js';
|
||||
import type {IFocusableNode} from './interfaces/i_focusable_node.js';
|
||||
import * as blocklyString from './utils/string.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
|
||||
@@ -363,6 +364,41 @@ export function hide() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the tooltip for a given target.
|
||||
*
|
||||
* @internal
|
||||
* @param target The node upon which the tooltip should be displayed.
|
||||
* @param workspace The target node's workspace.
|
||||
*/
|
||||
export function display(target: IFocusableNode, workspace?: WorkspaceSvg) {
|
||||
// If the target is not the same element currently displaying a tooltip, hide
|
||||
// the existing tooltip and set the target as our element.
|
||||
if (element !== target) {
|
||||
hide();
|
||||
poisonedElement = null;
|
||||
element = target;
|
||||
}
|
||||
|
||||
if (!element || !(element as AnyDuringMigration).tooltip) {
|
||||
// No tooltip here to show.
|
||||
return;
|
||||
} else if (blocked) {
|
||||
// Someone doesn't want us to show tooltips. We are probably handling a
|
||||
// user gesture, such as a click or drag.
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the position to just below the element with horizontal alignment based
|
||||
// on the target's RTL/LTR orientation.
|
||||
const targetRect = target.getFocusableElement().getBoundingClientRect();
|
||||
const rtl = element.RTL;
|
||||
lastX = rtl ? targetRect.x + targetRect.width : targetRect.x;
|
||||
lastY = targetRect.y + targetRect.height;
|
||||
|
||||
show(workspace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide any in-progress tooltips and block showing new tooltips until the next
|
||||
* call to unblock().
|
||||
|
||||
@@ -451,6 +451,7 @@
|
||||
"SHORTCUTS_PERFORM_ACTION": "Edit or confirm",
|
||||
"SHORTCUTS_DUPLICATE": "Duplicate",
|
||||
"SHORTCUTS_CLEANUP": "Clean up workspace",
|
||||
"SHORTCUTS_SHOW_TOOLTIP": "Show tooltip",
|
||||
"KEYBOARD_NAV_UNCONSTRAINED_MOVE_HINT": "Hold %1 and use arrow keys to move freely, then %2 to accept the position",
|
||||
"KEYBOARD_NAV_CONSTRAINED_MOVE_HINT": "Use the arrow keys to move, then %1 to accept the position",
|
||||
"KEYBOARD_NAV_COPIED_HINT": "Copied. Press %1 to paste.",
|
||||
|
||||
@@ -458,6 +458,7 @@
|
||||
"SHORTCUTS_PERFORM_ACTION": "shortcut display text for the perform action shortcut, which triggers an action on the focused element.",
|
||||
"SHORTCUTS_DUPLICATE": "shortcut display text for the duplicate shortcut, which duplicates the focused block or comment.",
|
||||
"SHORTCUTS_CLEANUP": "shortcut display text for the cleanup shortcut, which organizes blocks on the workspace.",
|
||||
"SHORTCUTS_SHOW_TOOLTIP": "shortcut display text for the show tooltip shortcut, which displays a short help text for the focused element.",
|
||||
"KEYBOARD_NAV_UNCONSTRAINED_MOVE_HINT": "Message shown to inform users how to move blocks to arbitrary locations with the keyboard.",
|
||||
"KEYBOARD_NAV_CONSTRAINED_MOVE_HINT": "Message shown to inform users how to move blocks with the keyboard.",
|
||||
"KEYBOARD_NAV_COPIED_HINT": "Message shown when an item is copied in keyboard navigation mode.",
|
||||
|
||||
@@ -1786,6 +1786,9 @@ Blockly.Msg.SHORTCUTS_DUPLICATE = 'Duplicate';
|
||||
/// shortcut display text for the cleanup shortcut, which organizes blocks on the workspace.
|
||||
Blockly.Msg.SHORTCUTS_CLEANUP = 'Clean up workspace';
|
||||
/** @type {string} */
|
||||
/// shortcut display text for the show tooltip shortcut, which displays a short help text for the focused element.
|
||||
Blockly.Msg.SHORTCUTS_SHOW_TOOLTIP = 'Show tooltip';
|
||||
/** @type {string} */
|
||||
/// Message shown to inform users how to move blocks to arbitrary locations
|
||||
/// with the keyboard.
|
||||
Blockly.Msg.KEYBOARD_NAV_UNCONSTRAINED_MOVE_HINT = 'Hold %1 and use arrow keys to move freely, then %2 to accept the position';
|
||||
|
||||
@@ -1435,4 +1435,55 @@ suite('Keyboard Shortcut Items', function () {
|
||||
assert.deepEqual(oldBounds, newBounds);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Show tooltip (Ctrl/Cmd+J)', function () {
|
||||
const event = createKeyDownEvent(Blockly.utils.KeyCodes.J, [
|
||||
Blockly.utils.KeyCodes.CTRL_CMD,
|
||||
]);
|
||||
|
||||
test('Displays tooltip on a block using the keyboard shortcut', function () {
|
||||
const block = this.workspace.newBlock('controls_if');
|
||||
Blockly.getFocusManager().focusNode(block);
|
||||
block.setTooltip('Tooltip Text');
|
||||
this.injectionDiv.dispatchEvent(event);
|
||||
|
||||
assert.isTrue(Blockly.Tooltip.isVisible());
|
||||
});
|
||||
|
||||
test('Displays new tooltip on a block using the keyboard shortcut if tooltip for another block is already displayed', function () {
|
||||
const block1 = this.workspace.newBlock('controls_if');
|
||||
const block2 = this.workspace.newBlock('logic_compare');
|
||||
|
||||
block1.setTooltip('block1');
|
||||
block2.setTooltip('block2');
|
||||
|
||||
// Set focus to block1 and show its tooltip
|
||||
Blockly.getFocusManager().focusNode(block1);
|
||||
this.injectionDiv.dispatchEvent(event);
|
||||
|
||||
// We have block1 focused; we should see block1's tooltip
|
||||
assert.isTrue(Blockly.Tooltip.isVisible());
|
||||
assert.isTrue(Blockly.Tooltip.getDiv().innerText === 'block1');
|
||||
|
||||
// Set focus to block2 and show its tooltip
|
||||
Blockly.getFocusManager().focusNode(block2);
|
||||
this.injectionDiv.dispatchEvent(event);
|
||||
|
||||
// Now we have block2 focused; we should see block2's tooltip
|
||||
assert.isTrue(Blockly.Tooltip.isVisible());
|
||||
assert.isTrue(Blockly.Tooltip.getDiv().innerText === 'block2');
|
||||
});
|
||||
|
||||
test('Do not show tooltip if drag in progress', function () {
|
||||
sinon.stub(this.workspace, 'isDragging').returns(true);
|
||||
this.injectionDiv.dispatchEvent(event);
|
||||
|
||||
const block = this.workspace.newBlock('controls_if');
|
||||
Blockly.getFocusManager().focusNode(block);
|
||||
block.setTooltip('Tooltip Text');
|
||||
this.injectionDiv.dispatchEvent(event);
|
||||
|
||||
assert.isFalse(Blockly.Tooltip.isVisible());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user