diff --git a/src/actions.js b/src/actions.js index 9d83efca7..3ec2c2a2e 100644 --- a/src/actions.js +++ b/src/actions.js @@ -185,10 +185,18 @@ export function activateByNid(nid, options) { // we just don't want to activate them.) if (!newNode) { return; } + // If the element has been ellided by CM, it won't be in the DOM. This + // can lead to situations where CM ellides the *currently-focused* elt, + // which confuses the screenreader. In these situations, we focus on + // a dummy element that just says "stand by" (see ToggleEditor.js). + // When the new node is available, focus will shift automatically. + if(!document.contains(newNode.element)) { + document.getElementById('SR_fix_for_slow_dom').focus(); + } + // If there's a previously-focused node, see if the ids match // If so, we need to manually initiate a new focus event if (newNode.nid === currentNode?.nid) { - //console.log('XXX actions.js:191, they are eq'); setTimeout(() => { if(newNode.element) newNode.element.focus(); }, 10); } @@ -210,17 +218,14 @@ export function activateByNid(nid, options) { // when double click because we can set focusId on the to-be-focused node setTimeout(() => { - //console.log('XXX actions:213 trying SET_FOCUS with fid=', focusId, 'fNId=', focusNId, 'xid=', node.id, 'xnid=', node.nid); dispatch({type: 'SET_FOCUS', focusId: newNode.id}); - //console.log('XXX actions:216'); if (options.record) { SHARED.search.setCursor(newNode.from); } - //console.log('XXX actions:220'); if (newNode.element) { const scroller = SHARED.cm.getScrollerElement(); - const wrapper = SHARED.cm.getWrapperElement(); + const wrapper = SHARED.cm.getWrapperElement(); if (options.allowMove) { SHARED.cm.scrollIntoView(newNode.from); @@ -237,7 +242,6 @@ export function activateByNid(nid, options) { scroller.setAttribute('aria-activedescendent', newNode.element.id); newNode.element.focus(); } - //console.log('XXX actions:240'); }, 25); }; } diff --git a/src/ui/BlockEditor.js b/src/ui/BlockEditor.js index 6f1a506fb..83e419d2f 100644 --- a/src/ui/BlockEditor.js +++ b/src/ui/BlockEditor.js @@ -279,6 +279,7 @@ class BlockEditor extends Component { const wrapper = ed.getWrapperElement(); wrapper.setAttribute('role', 'tree'); wrapper.setAttribute('aria-multiselectable', 'true'); + wrapper.setAttribute('tabIndex', -1); // pass the block-mode CM editor, API, and current AST onMount(ed, this.buildAPI(ed), ast); diff --git a/src/ui/Editor.less b/src/ui/Editor.less index a7a965003..977eb47b9 100644 --- a/src/ui/Editor.less +++ b/src/ui/Editor.less @@ -40,18 +40,30 @@ .blocks-toggle-btn, .bug-btn { position: absolute; + display: inline-flex; + align-items: center; top: 16px; right: 16px; z-index: 100; - width: 34px; height: 34px; + width: 34px; border-radius: 3px; font-size: 18pt; padding: 0px; + transition: width 0.25s linear; box-shadow: 2px 2px 2px black, 4px 4px 4px white; - &:focus { - outline: 0; - } + padding: 0px 4px; + &:focus { width: 175px; outline: 0; } + &:hover { width: 175px; } + .btn-title { font-size: 14px; } + } + /* hide button titles by default */ + .bug-btn .btn-title, .blocks-toggle-btn .btn-title { + position: absolute; clip: rect(0, 0, 0, 0); + } + .bug-btn:hover .btn-title, + .blocks-toggle-btn:hover .btn-title { + display: inline-block; clip: auto; position: relative; } .bug-btn { right: 64px; } } diff --git a/src/ui/EditorButtons.js b/src/ui/EditorButtons.js index 28cb90ad1..0599efc79 100644 --- a/src/ui/EditorButtons.js +++ b/src/ui/EditorButtons.js @@ -19,11 +19,10 @@ export class ToggleButton extends Component { const buttonIcon = this.props.blockMode? "✏️" : "🧱"; return ( ); } @@ -40,11 +39,10 @@ export class BugButton extends Component { render() { return ( ); } diff --git a/src/ui/ToggleEditor.js b/src/ui/ToggleEditor.js index 8653bf454..3664bc13b 100644 --- a/src/ui/ToggleEditor.js +++ b/src/ui/ToggleEditor.js @@ -208,6 +208,7 @@ export default @CMBContext class ToggleEditor extends Component { code = oldAst.toString() + (WS? WS[0] : ""); // pretty-print and restore whitespace this.ast = SHARED.parse(code); // parse the pretty-printed (PP) code } catch (e) { + console.error('COULD NOT PARSE PRETTY-PRINTED CODE:\n', code); throw `An error occured in the language module (the pretty-printer probably produced invalid code)`; } @@ -244,6 +245,10 @@ export default @CMBContext class ToggleEditor extends Component { +
+