Skip to content

Commit

Permalink
Merge pull request #2890 from WordPress/update/between-inserter
Browse files Browse the repository at this point in the history
Block List: Display inserter button after block on hover, focus
  • Loading branch information
gziolo authored Oct 9, 2017
2 parents 7dde319 + e3e0741 commit b6480da
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 63 deletions.
16 changes: 16 additions & 0 deletions components/dropdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ class Dropdown extends Component {
};
}

componentWillUnmount() {
const { isOpen } = this.state;
const { onToggle } = this.props;
if ( isOpen && onToggle ) {
onToggle( false );
}
}

componentWillUpdate( nextProps, nextState ) {
const { isOpen } = nextState;
const { onToggle } = nextProps;
if ( this.state.isOpen !== isOpen && onToggle ) {
onToggle( isOpen );
}
}

bindContainer( ref ) {
this.container = ref;
}
Expand Down
26 changes: 26 additions & 0 deletions editor/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,32 @@ export function hideInsertionPoint() {
};
}

/**
* Returns an action object used in signalling that block insertion should
* occur at the specified block index position.
*
* @param {Number} position Position at which to insert
* @return {Object} Action object
*/
export function setBlockInsertionPoint( position ) {
return {
type: 'SET_BLOCK_INSERTION_POINT',
position,
};
}

/**
* Returns an action object used in signalling that the block insertion point
* should be reset.
*
* @return {Object} Action object
*/
export function clearBlockInsertionPoint() {
return {
type: 'CLEAR_BLOCK_INSERTION_POINT',
};
}

export function editPost( edits ) {
return {
type: 'EDIT_POST',
Expand Down
13 changes: 7 additions & 6 deletions editor/assets/stylesheets/_z-index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@ $z-layers: (
'.editor-block-switcher__arrow': 1,
'.editor-visual-editor__block:before': -1,
'.editor-visual-editor__block .wp-block-more:before': -1,
'.editor-visual-editor__block {core/image aligned left or right}': 10,
'.editor-block-toolbar': 1,
'.editor-visual-editor__block {core/image aligned left or right}': 20,
'.editor-block-toolbar': 10,
'.editor-visual-editor__block-warning': 1,
'.editor-visual-editor .editor-visual-editor__block .editor-inserter': 1,
'.components-form-toggle__input': 1,
'.editor-format-list__menu': 1,
'.editor-inserter__tabs': 1,
'.editor-inserter__tab.is-active': 1,
'.components-panel__header': 1,
'.blocks-format-toolbar__link-modal': 1,
'.editor-block-switcher__menu': 2,
'.editor-block-mover': 10,
'.blocks-gallery-image__inline-menu': 10,
'.editor-header': 20,
'.editor-text-editor__formatting': 20,
'.editor-block-mover': 20,
'.blocks-gallery-image__inline-menu': 20,
'.editor-header': 30,
'.editor-text-editor__formatting': 30,

// Show drop zone above most standard content, but below any overlays
'.components-drop-zone': 100,
Expand Down
111 changes: 81 additions & 30 deletions editor/inserter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,99 @@
* External dependencies
*/
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Dropdown, IconButton } from '@wordpress/components';
import { createBlock } from '@wordpress/blocks';
import { Component } from '@wordpress/element';

/**
* Internal dependencies
*/
import InserterMenu from './menu';
import { getBlockInsertionPoint, getEditorMode } from '../selectors';
import { insertBlock, hideInsertionPoint } from '../actions';
import {
insertBlock,
setBlockInsertionPoint,
clearBlockInsertionPoint,
hideInsertionPoint,
} from '../actions';

function Inserter( { position, children, onInsertBlock, insertionPoint } ) {
return (
<Dropdown
className="editor-inserter"
position={ position }
renderToggle={ ( { onToggle, isOpen } ) => (
<IconButton
icon="insert"
label={ __( 'Insert block' ) }
onClick={ onToggle }
className="editor-inserter__toggle"
aria-haspopup="true"
aria-expanded={ isOpen }
>
{ children }
</IconButton>
) }
renderContent={ ( { onClose } ) => {
const onInsert = ( name ) => {
onInsertBlock(
name,
insertionPoint
);
class Inserter extends Component {
constructor() {
super( ...arguments );

onClose();
};
this.onToggle = this.onToggle.bind( this );
}

return <InserterMenu onSelect={ onInsert } />;
} }
/>
);
onToggle( isOpen ) {
const {
insertIndex,
setInsertionPoint,
clearInsertionPoint,
onToggle,
} = this.props;

// When inserting at specific index, assign as insertion point when
// the inserter is opened, clearing on close.
if ( insertIndex !== undefined ) {
if ( isOpen ) {
setInsertionPoint( insertIndex );
} else {
clearInsertionPoint();
}
}

// Surface toggle callback to parent component
if ( onToggle ) {
onToggle( isOpen );
}
}

render() {
const {
position,
children,
onInsertBlock,
insertionPoint,
} = this.props;

return (
<Dropdown
className="editor-inserter"
position={ position }
onToggle={ this.onToggle }
renderToggle={ ( { onToggle, isOpen } ) => (
<IconButton
icon="insert"
label={ __( 'Insert block' ) }
onClick={ onToggle }
className="editor-inserter__toggle"
aria-haspopup="true"
aria-expanded={ isOpen }
>
{ children }
</IconButton>
) }
renderContent={ ( { onClose } ) => {
const onInsert = ( name ) => {
onInsertBlock(
name,
insertionPoint
);

onClose();
};

return <InserterMenu onSelect={ onInsert } />;
} }
/>
);
}
}

export default connect(
Expand All @@ -65,5 +112,9 @@ export default connect(
position
) );
},
...bindActionCreators( {
setInsertionPoint: setBlockInsertionPoint,
clearInsertionPoint: clearBlockInsertionPoint,
}, dispatch ),
} )
)( Inserter );
22 changes: 12 additions & 10 deletions editor/inserter/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ export class InserterMenu extends Component {
}

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

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

componentDidUpdate( prevProps, prevState ) {
Expand Down Expand Up @@ -239,28 +239,32 @@ export class InserterMenu extends Component {
return;
}
this.focusPrevious( this );

break;

case UP:
keydown.preventDefault();
this.focusPrevious( this );

break;

case RIGHT:
if ( this.state.currentFocus === 'search' ) {
return;
}
this.focusNext( this );

break;

case DOWN:
keydown.preventDefault();
this.focusNext( this );

break;
default :
break;

default:
return;
}

// Since unhandled key will return in the default case, we can assume
// having reached this point implies that the key is handled.
keydown.stopImmediatePropagation();
}

changeMenuSelection( refName ) {
Expand Down Expand Up @@ -345,7 +349,6 @@ export class InserterMenu extends Component {
const isShowingEmbeds = ! isSearching && 'embeds' === this.state.tab;
const isShowingRecent = ! isSearching && 'recent' === this.state.tab;

/* eslint-disable jsx-a11y/no-autofocus */
return (
<div className="editor-inserter__menu">
<label htmlFor={ `editor-inserter__search-${ instanceId }` } className="screen-reader-text">
Expand Down Expand Up @@ -390,7 +393,6 @@ export class InserterMenu extends Component {
}
</div>
);
/* eslint-enable jsx-a11y/no-autofocus */
}
}

Expand Down
10 changes: 8 additions & 2 deletions editor/modes/visual-editor/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import BlockDropZone from './block-drop-zone';
import BlockMover from '../../block-mover';
import BlockRightMenu from '../../block-settings-menu';
import BlockToolbar from '../../block-toolbar';
import Inserter from '../../inserter';
import {
clearSelectedBlock,
editPost,
Expand Down Expand Up @@ -278,7 +279,7 @@ class VisualEditorBlock extends Component {
}

render() {
const { block, multiSelectedBlockUids, order } = this.props;
const { block, multiSelectedBlockUids, order, nextBlock } = this.props;
const { name: blockName, isValid } = block;
const blockType = getBlockType( blockName );
// translators: %s: Type of block (i.e. Text, Image etc)
Expand Down Expand Up @@ -310,7 +311,7 @@ class VisualEditorBlock extends Component {
'is-hovered': isHovered,
} );

const { onMouseLeave, onFocus, onReplace } = this.props;
const { onMouseLeave, onSelect, onFocus, onReplace } = this.props;

// Determine whether the block has props to apply to the wrapper.
let wrapperProps;
Expand Down Expand Up @@ -381,6 +382,11 @@ class VisualEditorBlock extends Component {
}
</BlockCrashBoundary>
</div>
{ ( showUI || isHovered ) && !! nextBlock && (
<Inserter
onToggle={ ( isOpen ) => isOpen ? onSelect() : null }
insertIndex={ order + 1 } />
) }
{ !! error && <BlockCrashWarning /> }
</div>
);
Expand Down
12 changes: 10 additions & 2 deletions editor/modes/visual-editor/inserter.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { createBlock } from '@wordpress/blocks';
*/
import Inserter from '../../inserter';
import { insertBlock } from '../../actions';
import { getBlockCount } from '../../selectors';

export class VisualEditorInserter extends Component {
constructor() {
Expand All @@ -42,6 +43,7 @@ export class VisualEditorInserter extends Component {
}

render() {
const { blockCount } = this.props;
const { isShowingControls } = this.state;
const classes = classnames( 'editor-visual-editor__inserter', {
'is-showing-controls': isShowingControls,
Expand All @@ -53,7 +55,9 @@ export class VisualEditorInserter extends Component {
onFocus={ this.showControls }
onBlur={ this.hideControls }
>
<Inserter position="top right" />
<Inserter
insertIndex={ blockCount }
position="top right" />
<IconButton
icon="editor-paragraph"
className="editor-inserter__block"
Expand All @@ -76,6 +80,10 @@ export class VisualEditorInserter extends Component {
}

export default connect(
null,
( state ) => {
return {
blockCount: getBlockCount( state ),
};
},
{ onInsertBlock: insertBlock },
)( VisualEditorInserter );
20 changes: 20 additions & 0 deletions editor/modes/visual-editor/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,26 @@
border-bottom: 3px solid $blue-medium-500;
}
}

.editor-visual-editor & .editor-inserter {
position: absolute;
left: $block-padding + $block-mover-padding-visible;
top: 100%;
transform: translate( -50%, -50% );
margin-top: 0;
margin-bottom: 0;
z-index: z-index( '.editor-visual-editor .editor-visual-editor__block .editor-inserter' );
}

.editor-visual-editor & .editor-inserter__toggle {
padding: 4px;
background-color: white;

&,
& .dashicon {
display: block;
}
}
}

.editor-visual-editor .editor-inserter {
Expand Down
Loading

0 comments on commit b6480da

Please sign in to comment.