Skip to content

Commit

Permalink
Add inert component to redirect unfocusable
Browse files Browse the repository at this point in the history
  • Loading branch information
aduth committed Jul 24, 2017
1 parent ac301a1 commit 7ad484f
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 11 deletions.
1 change: 1 addition & 0 deletions components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export { default as ExternalLink } from './external-link';
export { default as FormToggle } from './form-toggle';
export { default as FormTokenField } from './form-token-field';
export { default as IconButton } from './icon-button';
export { default as Inert } from './inert';
export { default as KeyboardShortcuts } from './keyboard-shortcuts';
export { default as Notice } from './notice';
export { default as NoticeList } from './notice/list';
Expand Down
104 changes: 104 additions & 0 deletions components/inert/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* WordPress dependencies
*/
import { Component } from 'element';

const focusable = [
'INPUT',
'SELECT',
'TEXTAREA',
'BUTTON',
'OBJECT',
];

function isFocusable( node ) {
if ( node.tabIndex < 0 ) {
return false;
} else if ( -1 !== focusable.indexOf( node.nodeName ) ) {
return ! node.disabled;
} else if ( 'A' === node.nodeName || 'AREA' === node.nodeName ) {
return node.hasAttribute( 'href' );
}

return node.tabIndex >= 0;
}

function getNextFocusable( node, siblingDirection ) {
let parent = node.parentNode;

let childDirection;
if ( 'nextSibling' === siblingDirection ) {
childDirection = 'firstChild';
} else {
childDirection = 'lastChild';
}

do {
while ( node[ siblingDirection ] ) {
if ( isFocusable( node[ siblingDirection ] ) ) {
return node[ siblingDirection ];
}

node = node[ siblingDirection ];
}

node = parent[ siblingDirection ];
if ( node ) {
while ( node[ childDirection ] ) {
node = node[ childDirection ];
}
} else {
node = parent;
}

if ( isFocusable( node ) ) {
return node;
}

parent = node.parentNode;
} while ( parent );
}

class Inert extends Component {
constructor() {
super( ...arguments );

this.onKeyPress = this.onKeyPress.bind( this );
}

componentDidMount() {
document.addEventListener( 'keydown', this.onKeyPress );
}

componentWillUnmount() {
document.removeEventListener( 'keydown', this.onKeyPress );
}

onKeyPress( event ) {
if ( event.which !== 9 ) {
return;
}

const testDirection = event.shiftKey ? 'nextSibling' : 'previousSibling';
if ( event.target !== getNextFocusable( this.node, testDirection ) ) {
return;
}

const nextDirection = event.shiftKey ? 'previousSibling' : 'nextSibling';
const nextFocusable = getNextFocusable( this.node, nextDirection );
if ( nextFocusable ) {
nextFocusable.focus();
event.preventDefault();
}
}

render() {
return (
<div ref={ ( node ) => this.node = node }>
{ this.props.children }
</div>
);
}
}

export default Inert;
26 changes: 15 additions & 11 deletions editor/modes/visual-editor/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
* WordPress dependencies
*/
import { Children, Component } from 'element';
import { IconButton, Toolbar } from 'components';
import { IconButton, Toolbar, Inert } from 'components';
import { BACKSPACE, ESCAPE, DELETE, UP, DOWN, LEFT, RIGHT } from 'utils/keycodes';
import { getBlockType, getBlockDefaultClassname } from 'blocks';
import { __, sprintf } from 'i18n';
Expand Down Expand Up @@ -344,6 +344,19 @@ class VisualEditorBlock extends Component {
wrapperProps = blockType.getEditWrapperProps( block.attributes );
}

const edit = (
<BlockEdit
focus={ focus }
attributes={ block.attributes }
setAttributes={ this.setAttributes }
insertBlocksAfter={ onInsertBlocksAfter }
setFocus={ partial( onFocus, block.uid ) }
mergeBlocks={ this.mergeBlocks }
className={ classnames( className, block.attributes.className ) }
id={ block.uid }
/>
);

// Disable reason: Each block can be selected by clicking on it
/* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */
return (
Expand Down Expand Up @@ -399,16 +412,7 @@ class VisualEditorBlock extends Component {
onTouchStart={ this.onPointerDown }
className="editor-visual-editor__block-edit"
>
<BlockEdit
focus={ focus }
attributes={ block.attributes }
setAttributes={ this.setAttributes }
insertBlocksAfter={ onInsertBlocksAfter }
setFocus={ partial( onFocus, block.uid ) }
mergeBlocks={ this.mergeBlocks }
className={ classnames( className, block.attributes.className ) }
id={ block.uid }
/>
{ isValid ? edit : <Inert>{ edit }</Inert> }
</div>
{ ! isValid && <InvalidBlockWarning /> }
</div>
Expand Down

0 comments on commit 7ad484f

Please sign in to comment.