Skip to content

Commit f0092da

Browse files
Add plugin, fix focus outlines
Maybe we'll want workspace focus to be inside of the toolbox, TBD. Plugin based on the Blockly 11 commit of RaspberryPiFoundation/blockly-keyboard-experimentation#358
1 parent c4d54f9 commit f0092da

File tree

5 files changed

+69
-26
lines changed

5 files changed

+69
-26
lines changed
121 KB
Binary file not shown.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
},
6363
"dependencies": {
6464
"@blockly/field-colour": "5.0.5",
65-
"@blockly/keyboard-experiment": "0.0.1",
65+
"@blockly/keyboard-experiment": "file:blockly-keyboard-experiment-0.0.5.tgz",
6666
"@blockly/plugin-workspace-search": "9.1.0",
6767
"@crowdin/crowdin-api-client": "^1.33.0",
6868
"@fortawesome/fontawesome-free": "^5.15.4",

theme/blockly-core.less

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,7 @@ svg.blocklySvg {
5050
}
5151
}
5252

53-
.blocklyWorkspace:focus {
54-
outline: none;
55-
}
56-
.blocklyWorkspace:focus-visible .blocklyMainBackground {
57-
outline: 5px solid black;
58-
outline-offset: -5px;
59-
}
53+
6054

6155
.blocklyMainBackground {
6256
stroke: none !important;
@@ -390,3 +384,45 @@ text.blocklyCheckbox {
390384
font-size: 17pt !important;
391385
}
392386
}
387+
388+
389+
/*******************************
390+
Focus styles
391+
*******************************/
392+
393+
.accessibleBlocks .blocklyWorkspace:focus,.blocklyWorkspaceFocusLayer:focus {
394+
outline: none;
395+
}
396+
397+
.accessibleBlocks .blocklyWorkspaceFocusRingLayer {
398+
position: absolute;
399+
top: 0;
400+
left: 0;
401+
bottom: 0;
402+
right: 0;
403+
pointer-events: none;
404+
z-index: 99;
405+
}
406+
407+
.accessibleBlocks .blocklyWorkspaceFocusRingLayer[data-focused = 'true'] {
408+
outline: 3px solid black;
409+
outline-offset: -3px;
410+
}
411+
412+
div.blocklyTreeRoot > div[role="tree"]:focus-visible {
413+
outline: none;
414+
}
415+
416+
.accessibleBlocks div.blocklyTreeRoot > div[role="tree"]:focus-visible {
417+
outline: 3px solid black;
418+
outline-offset: -3px;
419+
}
420+
421+
.accessibleBlocks .blocklyFlyout:focus {
422+
outline: none;
423+
}
424+
425+
.accessibleBlocks .blocklyFlyout:focus-visible {
426+
outline: 3px solid black;
427+
outline-offset: -3px;
428+
}

theme/toolbox.less

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,6 @@ div.blocklyTreeRoot:focus {
5959
outline: none;
6060
}
6161

62-
div.blocklyTreeRoot > div[role="tree"]:focus-visible {
63-
outline: 3px solid black;
64-
outline-offset: -3px;
65-
}
66-
67-
div.blocklyTreeRoot > div[role="tree"] > div:focus-visible {
68-
outline: none;
69-
}
70-
7162
/*******************************
7263
Toolbox tree row
7364
*******************************/

webapp/src/blocks.tsx

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -498,16 +498,19 @@ export class Editor extends toolboxeditor.ToolboxEditor {
498498

499499
/**
500500
* Override blockly methods to support our custom toolbox.
501+
*
502+
* We don't generally use this selection but keyboard nav will trigger
503+
* it to select the first category and clear the selection.
501504
*/
502505
const that = this;
503-
(Blockly as any).Toolbox.prototype.updateFlyout_ = function (oldItem: Blockly.ISelectableToolboxItem | null, newItem: Blockly.ISelectableToolboxItem | null) {
504-
// Keyboard nav triggers selection on the Blockly toolbox
505-
// (first item + clear as we intercept all other events).
506-
// Hook in just to hide the flyout when selection is cleared.
506+
(Blockly as any).Toolbox.prototype.setSelectedItem = function (newItem: Blockly.ISelectableToolboxItem | null) {
507507
if (newItem === null) {
508508
that.hideFlyout();
509509
}
510510
};
511+
(Blockly as any).Toolbox.prototype.clearSelection = function () {
512+
that.hideFlyout();
513+
};
511514
(Blockly.WorkspaceSvg as any).prototype.refreshToolboxSelection = function () {
512515
let ws = this.isFlyout ? this.targetWorkspace : this;
513516
if (ws && !ws.currentGesture_ && ws.toolbox_ && ws.toolbox_.flyout_) {
@@ -547,6 +550,17 @@ export class Editor extends toolboxeditor.ToolboxEditor {
547550
const enabled = pxt.appTarget.appTheme?.accessibleBlocks;
548551
if (enabled && !this.keyboardNavigation) {
549552
this.keyboardNavigation = new KeyboardNavigation(this.editor);
553+
554+
const injectionDiv = document.getElementById('blocksEditor');
555+
injectionDiv.classList.add("accessibleBlocks");
556+
const focusRingDiv = injectionDiv.appendChild(document.createElement("div"))
557+
focusRingDiv.className = "blocklyWorkspaceFocusRingLayer";
558+
this.editor.getSvgGroup().addEventListener("focus", () => {
559+
focusRingDiv.dataset.focused = "true";
560+
})
561+
this.editor.getSvgGroup().addEventListener("blur", () => {
562+
delete focusRingDiv.dataset.focused;
563+
})
550564
}
551565
}
552566

@@ -937,21 +951,23 @@ export class Editor extends toolboxeditor.ToolboxEditor {
937951
if (pxt.shell.isReadOnly()) return;
938952
const blocklyToolboxDiv = this.getBlocklyToolboxDiv();
939953
const blocklyToolbox = <div className="blocklyToolbox">
940-
<div className="blocklyToolboxContents" tabIndex={-1}>
954+
<div className="blocklyToolboxContents" tabIndex={-1} onFocus={this.handleToolboxContentsFocusCapture}>
941955
<toolbox.Toolbox ref={this.handleToolboxRef} editorname="blocks" parent={this} />
942956
{<div id="debuggerToolbox"></div>}
943957
</div>
944958
</div>;
945959
Util.assert(!!blocklyToolboxDiv);
946960
ReactDOM.render(blocklyToolbox, blocklyToolboxDiv);
947-
blocklyToolboxDiv.querySelector(".blocklyToolboxContents").addEventListener("focus", () => {
948-
console.log("Did it happen?");
949-
(blocklyToolboxDiv.querySelector("[role=tree]") as HTMLElement).focus()
950-
})
951961

952962
if (!immediate) this.toolbox.showLoading();
953963
}
954964

965+
private handleToolboxContentsFocusCapture = (e: React.FocusEvent) => {
966+
if (e.target === e.currentTarget) {
967+
(this.getBlocklyToolboxDiv().querySelector("[role=tree]") as HTMLElement).focus()
968+
}
969+
}
970+
955971
updateToolbox() {
956972
const container = document.getElementById('debuggerToolbox');
957973
if (!container) return;

0 commit comments

Comments
 (0)