From 4d5fa382002b34da57204d00d6126796f32903b8 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 10 Apr 2018 16:21:02 +0100 Subject: [PATCH 1/7] Block: Adding the left/right block hover areas Show movers on the left and settings on the right --- editor/components/block-list/block.js | 10 ++- .../components/block-list/with-hover-areas.js | 68 +++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 editor/components/block-list/with-hover-areas.js diff --git a/editor/components/block-list/block.js b/editor/components/block-list/block.js index 778cd1d7235b14..b93526d242b1fe 100644 --- a/editor/components/block-list/block.js +++ b/editor/components/block-list/block.js @@ -48,6 +48,7 @@ import BlockDraggable from './block-draggable'; import IgnoreNestedEvents from './ignore-nested-events'; import InserterWithShortcuts from '../inserter-with-shortcuts'; import Inserter from '../inserter'; +import withHoverAreas from './with-hover-areas'; import { createInnerBlockList } from '../../utils/block-list'; const { BACKSPACE, DELETE, ENTER } = keycodes; @@ -404,8 +405,10 @@ export class BlockListBlock extends Component { isFirstMultiSelected, isLastInSelection, isTypingWithinBlock, + isMultiSelecting, + hoverArea, } = this.props; - const isHovered = this.state.isHovered && ! this.props.isMultiSelecting; + const isHovered = this.state.isHovered && ! isMultiSelecting; const { name: blockName, isValid } = block; const blockType = getBlockType( blockName ); // translators: %s: Type of block (i.e. Text, Image etc) @@ -419,8 +422,8 @@ export class BlockListBlock extends Component { const isSelectedNotTyping = isSelected && ! isTypingWithinBlock; const showSideInserter = ( isSelected || isHovered ) && isEmptyDefaultBlock; const shouldAppearSelected = ! showSideInserter && isSelectedNotTyping; - const shouldShowMovers = ( shouldAppearSelected || isHovered || ( isEmptyDefaultBlock && isSelectedNotTyping ) ) && ! showSideInserter; - const shouldShowSettingsMenu = shouldShowMovers; + const shouldShowMovers = ( isSelectedNotTyping || hoverArea === 'left' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; + const shouldShowSettingsMenu = ( isSelectedNotTyping || hoverArea === 'right' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; const shouldShowContextualToolbar = shouldAppearSelected && isValid && showContextualToolbar; const shouldShowMobileToolbar = shouldAppearSelected; const { error, dragging } = this.state; @@ -692,4 +695,5 @@ export default compose( }; } ), withFilters( 'editor.BlockListBlock' ), + withHoverAreas )( BlockListBlock ); diff --git a/editor/components/block-list/with-hover-areas.js b/editor/components/block-list/with-hover-areas.js new file mode 100644 index 00000000000000..072d1789cd5dcb --- /dev/null +++ b/editor/components/block-list/with-hover-areas.js @@ -0,0 +1,68 @@ +/** + * WordPress dependencies + */ +import { Component, findDOMNode } from '@wordpress/element'; + +/** + * Module constants + */ +const HOVER_AREA_SIZE = 120; + +const withHoverAreas = ( WrappedComponent ) => { + class WithHoverAreasComponent extends Component { + constructor() { + super( ...arguments ); + this.state = { + hoverArea: null, + }; + this.onMouseLeave = this.onMouseLeave.bind( this ); + this.onMouseMove = this.onMouseMove.bind( this ); + } + + componentDidMount() { + // Disable reason: We use findDOMNode to avoid unnecessary extra dom Nodes + // eslint-disable-next-line react/no-find-dom-node + this.container = findDOMNode( this ); + this.container.addEventListener( 'mousemove', this.onMouseMove ); + this.container.addEventListener( 'mouseleave', this.onMouseLeave ); + } + + componentWillUnmount() { + this.container.removeEventListener( 'mousemove', this.onMouseMove ); + this.container.removeEventListener( 'mouseleave', this.onMouseLeave ); + } + + onMouseLeave() { + if ( this.state.hoverArea ) { + this.setState( { hoverArea: null } ); + } + } + + onMouseMove( event ) { + const { width, left, right } = this.container.getBoundingClientRect(); + const isSmall = width < ( HOVER_AREA_SIZE * 2 ) + 10; + + let hoverArea = null; + if ( ( event.clientX - left ) < ( isSmall ? width / 2 : HOVER_AREA_SIZE ) ) { + hoverArea = 'left'; + } else if ( ( right - event.clientX ) < ( isSmall ? width / 2 : HOVER_AREA_SIZE ) ) { + hoverArea = 'right'; + } + + if ( hoverArea !== this.state.hoverArea ) { + this.setState( { hoverArea } ); + } + } + + render() { + const { hoverArea } = this.state; + return ( + + ); + } + } + + return WithHoverAreasComponent; +}; + +export default withHoverAreas; From 63e4c8183f9aaf0604fa260d6b5fe614df2f37db Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Apr 2018 10:22:41 +0100 Subject: [PATCH 2/7] Extend the hover areas behavior to the selected block and add animations --- edit-post/assets/stylesheets/_animations.scss | 12 ++ editor/components/block-list/block.js | 11 +- editor/components/block-mover/index.js | 134 +++++++++++------- editor/components/block-mover/style.scss | 8 ++ .../components/block-settings-menu/index.js | 125 ++++++++++------ .../components/block-settings-menu/style.scss | 8 ++ 6 files changed, 195 insertions(+), 103 deletions(-) diff --git a/edit-post/assets/stylesheets/_animations.scss b/edit-post/assets/stylesheets/_animations.scss index dad82172b52768..2a6a365b1b56a0 100644 --- a/edit-post/assets/stylesheets/_animations.scss +++ b/edit-post/assets/stylesheets/_animations.scss @@ -17,4 +17,16 @@ animation: slide_in_right 0.1s forwards; } +@mixin fade_in { + animation: fade-in 0.5s ease-out; + animation-fill-mode: forwards; +} +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/editor/components/block-list/block.js b/editor/components/block-list/block.js index b93526d242b1fe..5418632a0e3eb1 100644 --- a/editor/components/block-list/block.js +++ b/editor/components/block-list/block.js @@ -422,8 +422,9 @@ export class BlockListBlock extends Component { const isSelectedNotTyping = isSelected && ! isTypingWithinBlock; const showSideInserter = ( isSelected || isHovered ) && isEmptyDefaultBlock; const shouldAppearSelected = ! showSideInserter && isSelectedNotTyping; - const shouldShowMovers = ( isSelectedNotTyping || hoverArea === 'left' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; - const shouldShowSettingsMenu = ( isSelectedNotTyping || hoverArea === 'right' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; + // We render block movers and block settings to keep them tabbale even if hidden + const shouldRenderMovers = ( isSelected || hoverArea === 'left' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; + const shouldRenderBlockSettings = ( isSelected || hoverArea === 'right' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; const shouldShowContextualToolbar = shouldAppearSelected && isValid && showContextualToolbar; const shouldShowMobileToolbar = shouldAppearSelected; const { error, dragging } = this.state; @@ -513,20 +514,22 @@ export class BlockListBlock extends Component { rootUID={ rootUID } layout={ layout } /> - { shouldShowMovers && ( + { shouldRenderMovers && ( ) } - { shouldShowSettingsMenu && ! showSideInserter && ( + { shouldRenderBlockSettings && ( ) } { isHovered && } diff --git a/editor/components/block-mover/index.js b/editor/components/block-mover/index.js index a96196be8fcfb0..42947bdad91a04 100644 --- a/editor/components/block-mover/index.js +++ b/editor/components/block-mover/index.js @@ -3,6 +3,7 @@ */ import { connect } from 'react-redux'; import { first } from 'lodash'; +import classnames from 'classnames'; /** * WordPress dependencies @@ -10,7 +11,7 @@ import { first } from 'lodash'; import { __ } from '@wordpress/i18n'; import { IconButton, withContext, withInstanceId } from '@wordpress/components'; import { getBlockType } from '@wordpress/blocks'; -import { compose } from '@wordpress/element'; +import { compose, Component } from '@wordpress/element'; /** * Internal dependencies @@ -20,59 +21,88 @@ import { getBlockMoverDescription } from './mover-description'; import { getBlockIndex, getBlock } from '../../store/selectors'; import { upArrow, downArrow } from './arrows'; -export function BlockMover( { onMoveUp, onMoveDown, isFirst, isLast, uids, blockType, firstIndex, isLocked, instanceId } ) { - if ( isLocked ) { - return null; +export class BlockMover extends Component { + constructor() { + super( ...arguments ); + this.state = { + isFocused: false, + }; + this.onFocus = this.onFocus.bind( this ); + this.onBlur = this.onBlur.bind( this ); + } + + onFocus() { + this.setState( { + isFocused: true, + } ); } - // We emulate a disabled state because forcefully applying the `disabled` - // attribute on the button while it has focus causes the screen to change - // to an unfocused state (body as active element) without firing blur on, - // the rendering parent, leaving it unable to react to focus out. - return ( -
- - - - { - getBlockMoverDescription( - uids.length, - blockType && blockType.title, - firstIndex, - isFirst, - isLast, - -1, - ) - } - - - { - getBlockMoverDescription( - uids.length, - blockType && blockType.title, - firstIndex, - isFirst, - isLast, - 1, - ) - } - -
- ); + onBlur() { + this.setState( { + isFocused: false, + } ); + } + + render() { + const { onMoveUp, onMoveDown, isFirst, isLast, uids, blockType, firstIndex, isLocked, instanceId, isHidden } = this.props; + const { isFocused } = this.state; + if ( isLocked ) { + return null; + } + + // We emulate a disabled state because forcefully applying the `disabled` + // attribute on the button while it has focus causes the screen to change + // to an unfocused state (body as active element) without firing blur on, + // the rendering parent, leaving it unable to react to focus out. + return ( +
+ + + + { + getBlockMoverDescription( + uids.length, + blockType && blockType.title, + firstIndex, + isFirst, + isLast, + -1, + ) + } + + + { + getBlockMoverDescription( + uids.length, + blockType && blockType.title, + firstIndex, + isFirst, + isLast, + 1, + ) + } + +
+ ); + } } /** diff --git a/editor/components/block-mover/style.scss b/editor/components/block-mover/style.scss index 314ec7fa168cba..3f354c30d8a7b2 100644 --- a/editor/components/block-mover/style.scss +++ b/editor/components/block-mover/style.scss @@ -1,3 +1,11 @@ +.editor-block-mover { + opacity: 0; + + &.is-visible { + @include fade_in; + } +} + // Mover icon buttons .editor-block-mover__control { display: block; diff --git a/editor/components/block-settings-menu/index.js b/editor/components/block-settings-menu/index.js index 690bd0012799b5..9aee875e2e9d36 100644 --- a/editor/components/block-settings-menu/index.js +++ b/editor/components/block-settings-menu/index.js @@ -8,6 +8,7 @@ import { connect } from 'react-redux'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { Component } from '@wordpress/element'; import { IconButton, Dropdown, NavigableMenu } from '@wordpress/components'; /** @@ -22,56 +23,86 @@ import SharedBlockSettings from './shared-block-settings'; import UnknownConverter from './unknown-converter'; import { selectBlock } from '../../store/actions'; -function BlockSettingsMenu( { - uids, - onSelect, - focus, - rootUID, - renderBlockMenu = ( { children } ) => children, -} ) { - const count = uids.length; +export class BlockSettingsMenu extends Component { + constructor() { + super( ...arguments ); + this.state = { + isFocused: false, + }; + this.onFocus = this.onFocus.bind( this ); + this.onBlur = this.onBlur.bind( this ); + } - return ( - { - const toggleClassname = classnames( 'editor-block-settings-menu__toggle', { - 'is-opened': isOpen, - } ); + onFocus() { + this.setState( { + isFocused: true, + } ); + } - return ( - { - if ( uids.length === 1 ) { - onSelect( uids[ 0 ] ); - } - onToggle(); - } } - icon="ellipsis" - label={ __( 'More Options' ) } - aria-expanded={ isOpen } - focus={ focus } - /> - ); - } } - renderContent={ ( { onClose } ) => ( + onBlur() { + this.setState( { + isFocused: false, + } ); + } + + render() { + const { + uids, + onSelect, + focus, + rootUID, + renderBlockMenu = ( { children } ) => children, + isHidden, + } = this.props; + const { isFocused } = this.state; + const count = uids.length; + + return ( + { + const toggleClassname = classnames( 'editor-block-settings-menu__toggle', { + 'is-opened': isOpen, + } ); + + return ( + { + if ( uids.length === 1 ) { + onSelect( uids[ 0 ] ); + } + onToggle(); + } } + icon="ellipsis" + label={ __( 'More Options' ) } + aria-expanded={ isOpen } + focus={ focus } + onFocus={ this.onFocus } + onBlur={ this.onBlur } + /> + ); + } } + renderContent={ ( { onClose } ) => ( // Should this just use a DropdownMenu instead of a DropDown ? - - { renderBlockMenu( { onClose, children: [ - count === 1 && , - count === 1 && , - , - , - count === 1 && , - , - ] } ) } - - ) } - /> - ); + + { renderBlockMenu( { onClose, children: [ + count === 1 && , + count === 1 && , + , + , + count === 1 && , + , + ] } ) } + + ) } + /> + ); + } } export default connect( diff --git a/editor/components/block-settings-menu/style.scss b/editor/components/block-settings-menu/style.scss index 278e485aaf8736..64af209122f30e 100644 --- a/editor/components/block-settings-menu/style.scss +++ b/editor/components/block-settings-menu/style.scss @@ -1,3 +1,11 @@ +.editor-block-settings-menu { + opacity: 0; + + &.is-visible { + @include fade_in; + } +} + // The Blocks "More" Menu ellipsis icon button .editor-block-settings-menu__toggle { justify-content: center; From fc2efa4f70b2999eca73e9823e628208e9089926 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Apr 2018 10:49:45 +0100 Subject: [PATCH 3/7] Make the hover areas a little bit bigger --- editor/components/block-list/with-hover-areas.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/editor/components/block-list/with-hover-areas.js b/editor/components/block-list/with-hover-areas.js index 072d1789cd5dcb..fb381d3624726f 100644 --- a/editor/components/block-list/with-hover-areas.js +++ b/editor/components/block-list/with-hover-areas.js @@ -3,11 +3,6 @@ */ import { Component, findDOMNode } from '@wordpress/element'; -/** - * Module constants - */ -const HOVER_AREA_SIZE = 120; - const withHoverAreas = ( WrappedComponent ) => { class WithHoverAreasComponent extends Component { constructor() { @@ -40,12 +35,11 @@ const withHoverAreas = ( WrappedComponent ) => { onMouseMove( event ) { const { width, left, right } = this.container.getBoundingClientRect(); - const isSmall = width < ( HOVER_AREA_SIZE * 2 ) + 10; let hoverArea = null; - if ( ( event.clientX - left ) < ( isSmall ? width / 2 : HOVER_AREA_SIZE ) ) { + if ( ( event.clientX - left ) < width / 3 ) { hoverArea = 'left'; - } else if ( ( right - event.clientX ) < ( isSmall ? width / 2 : HOVER_AREA_SIZE ) ) { + } else if ( ( right - event.clientX ) < width / 3 ) { hoverArea = 'right'; } From 3d4a22dafccb1a21f90970ff71db6d609048a776 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 12 Apr 2018 08:59:00 +0100 Subject: [PATCH 4/7] Show breadcrumb only when we're close --- edit-post/assets/stylesheets/_animations.scss | 11 +---------- edit-post/assets/stylesheets/main.scss | 9 +++++++++ editor/components/block-list/block.js | 3 ++- editor/components/block-list/breadcrumb.js | 11 +++++++++-- editor/components/block-list/style.scss | 8 ++++++++ 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/edit-post/assets/stylesheets/_animations.scss b/edit-post/assets/stylesheets/_animations.scss index 2a6a365b1b56a0..2b65713d45f1f4 100644 --- a/edit-post/assets/stylesheets/_animations.scss +++ b/edit-post/assets/stylesheets/_animations.scss @@ -18,15 +18,6 @@ } @mixin fade_in { - animation: fade-in 0.5s ease-out; + animation: fade-in 0.3s ease-out; animation-fill-mode: forwards; } - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} diff --git a/edit-post/assets/stylesheets/main.scss b/edit-post/assets/stylesheets/main.scss index 63effc808923de..8a7f6754f973ff 100644 --- a/edit-post/assets/stylesheets/main.scss +++ b/edit-post/assets/stylesheets/main.scss @@ -147,3 +147,12 @@ body.gutenberg-editor-page { padding: 6px 10px; } } + +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/editor/components/block-list/block.js b/editor/components/block-list/block.js index 5418632a0e3eb1..4be099e57cabb9 100644 --- a/editor/components/block-list/block.js +++ b/editor/components/block-list/block.js @@ -425,6 +425,7 @@ export class BlockListBlock extends Component { // We render block movers and block settings to keep them tabbale even if hidden const shouldRenderMovers = ( isSelected || hoverArea === 'left' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; const shouldRenderBlockSettings = ( isSelected || hoverArea === 'right' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; + const shouldShowBreadcrumb = isHovered; const shouldShowContextualToolbar = shouldAppearSelected && isValid && showContextualToolbar; const shouldShowMobileToolbar = shouldAppearSelected; const { error, dragging } = this.state; @@ -532,7 +533,7 @@ export class BlockListBlock extends Component { isHidden={ hoverArea !== 'right' } /> ) } - { isHovered && } + { shouldShowBreadcrumb && } { shouldShowContextualToolbar && } { isFirstMultiSelected && } + { rootUID && ( diff --git a/editor/components/block-list/style.scss b/editor/components/block-list/style.scss index b436bb81af932e..b8470cea49a24a 100644 --- a/editor/components/block-list/style.scss +++ b/editor/components/block-list/style.scss @@ -699,3 +699,11 @@ padding-top: 6px; } } + +.editor-block-breadcrumb { + opacity: 0; + + &.is-visible { + @include fade_in; + } +} From bf2731fa0a1e05e2e28353a52c92d646bd8be6c5 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 12 Apr 2018 09:02:29 +0100 Subject: [PATCH 5/7] Fix small bug where the movers are stuck --- editor/components/block-list/block.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/components/block-list/block.js b/editor/components/block-list/block.js index 4be099e57cabb9..7f3eeef7ef917a 100644 --- a/editor/components/block-list/block.js +++ b/editor/components/block-list/block.js @@ -423,8 +423,8 @@ export class BlockListBlock extends Component { const showSideInserter = ( isSelected || isHovered ) && isEmptyDefaultBlock; const shouldAppearSelected = ! showSideInserter && isSelectedNotTyping; // We render block movers and block settings to keep them tabbale even if hidden - const shouldRenderMovers = ( isSelected || hoverArea === 'left' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; - const shouldRenderBlockSettings = ( isSelected || hoverArea === 'right' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; + const shouldRenderMovers = isHovered && ( isSelected || hoverArea === 'left' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; + const shouldRenderBlockSettings = isHovered && ( isSelected || hoverArea === 'right' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; const shouldShowBreadcrumb = isHovered; const shouldShowContextualToolbar = shouldAppearSelected && isValid && showContextualToolbar; const shouldShowMobileToolbar = shouldAppearSelected; From 667905e470c4e78cf3376169190a1a8015f61c4a Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 12 Apr 2018 09:09:28 +0100 Subject: [PATCH 6/7] Show the breadcrumb when it's focused --- editor/components/block-list/breadcrumb.js | 90 +++++++++++++--------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/editor/components/block-list/breadcrumb.js b/editor/components/block-list/breadcrumb.js index 5dc73a502cabbb..466f93c132bec3 100644 --- a/editor/components/block-list/breadcrumb.js +++ b/editor/components/block-list/breadcrumb.js @@ -6,7 +6,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { compose } from '@wordpress/element'; +import { compose, Component } from '@wordpress/element'; import { Dashicon, Tooltip, Toolbar, Button } from '@wordpress/components'; import { withDispatch, withSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; @@ -17,20 +17,6 @@ import { __ } from '@wordpress/i18n'; import NavigableToolbar from '../navigable-toolbar'; import BlockTitle from '../block-title'; -/** - * Stops propagation of the given event argument. Assumes that the event has - * been completely handled and no other listeners should be informed. - * - * For the breadcrumb component, this is used for improved interoperability - * with the block's `onFocus` handler which selects the block, thus conflicting - * with the intention to select the root block. - * - * @param {Event} event Event for which propagation should be stopped. - */ -function stopPropagation( event ) { - event.stopPropagation(); -} - /** * Block breadcrumb component, displaying the label of the block. If the block * descends from a root block, a button is displayed enabling the user to select @@ -39,29 +25,59 @@ function stopPropagation( event ) { * @param {string} props.uid UID of block. * @param {string} props.rootUID UID of block's root. * @param {Function} props.selectRootBlock Callback to select root block. - * - * @return {WPElement} Breadcrumb element. */ -function BlockBreadcrumb( { uid, rootUID, selectRootBlock, isHidden } ) { - return ( - - - { rootUID && ( - - - - ) } - - - - ); +export class BlockBreadcrumb extends Component { + constructor() { + super( ...arguments ); + this.state = { + isFocused: false, + }; + this.onFocus = this.onFocus.bind( this ); + this.onBlur = this.onBlur.bind( this ); + } + + onFocus( event ) { + this.setState( { + isFocused: true, + } ); + + // This is used for improved interoperability + // with the block's `onFocus` handler which selects the block, thus conflicting + // with the intention to select the root block. + event.stopPropagation(); + } + + onBlur() { + this.setState( { + isFocused: false, + } ); + } + + render( ) { + const { uid, rootUID, selectRootBlock, isHidden } = this.props; + const { isFocused } = this.state; + + return ( + + + { rootUID && ( + + + + ) } + + + + ); + } } export default compose( [ From f614065764b6b1aeb3d2ebf7676def3d5c151512 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 12 Apr 2018 09:12:19 +0100 Subject: [PATCH 7/7] Fix keyboard navigation to movers and block settings menu --- editor/components/block-list/block.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editor/components/block-list/block.js b/editor/components/block-list/block.js index 7f3eeef7ef917a..a0206c55d241f0 100644 --- a/editor/components/block-list/block.js +++ b/editor/components/block-list/block.js @@ -423,8 +423,8 @@ export class BlockListBlock extends Component { const showSideInserter = ( isSelected || isHovered ) && isEmptyDefaultBlock; const shouldAppearSelected = ! showSideInserter && isSelectedNotTyping; // We render block movers and block settings to keep them tabbale even if hidden - const shouldRenderMovers = isHovered && ( isSelected || hoverArea === 'left' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; - const shouldRenderBlockSettings = isHovered && ( isSelected || hoverArea === 'right' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; + const shouldRenderMovers = ( isSelected || hoverArea === 'left' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; + const shouldRenderBlockSettings = ( isSelected || hoverArea === 'right' ) && ! showSideInserter && ! isMultiSelecting && ! isMultiSelected; const shouldShowBreadcrumb = isHovered; const shouldShowContextualToolbar = shouldAppearSelected && isValid && showContextualToolbar; const shouldShowMobileToolbar = shouldAppearSelected; @@ -522,7 +522,7 @@ export class BlockListBlock extends Component { layout={ layout } isFirst={ isFirst } isLast={ isLast } - isHidden={ hoverArea !== 'left' } + isHidden={ ! isHovered || hoverArea !== 'left' } /> ) } { shouldRenderBlockSettings && ( @@ -530,7 +530,7 @@ export class BlockListBlock extends Component { uids={ [ uid ] } rootUID={ rootUID } renderBlockMenu={ renderBlockMenu } - isHidden={ hoverArea !== 'right' } + isHidden={ ! isHovered || hoverArea !== 'right' } /> ) } { shouldShowBreadcrumb && }