Skip to content

Commit

Permalink
G2: Movers - Try show/hide interaction
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Q committed Feb 5, 2020
1 parent e522228 commit 79b0327
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ import NavigableToolbar from '../navigable-toolbar';
import { BlockToolbar } from '../';

function BlockContextualToolbar( { focusOnMount, ...props } ) {
// TODO: Remove this work-around
const forcedMarginNormlizedStyles = { marginLeft: 0 };
return (
<NavigableToolbar
focusOnMount={ focusOnMount }
className="block-editor-block-contextual-toolbar"
/* translators: accessibility text for the block toolbar */
aria-label={ __( 'Block tools' ) }
style={ forcedMarginNormlizedStyles }
{ ...props }
>
<BlockToolbar />
Expand Down
104 changes: 100 additions & 4 deletions packages/block-editor/src/components/block-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';

import { useState, useRef, useEffect } from '@wordpress/element';
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* Internal dependencies
*/
Expand All @@ -27,6 +31,7 @@ export default function BlockToolbar( { hideDragHandle } ) {
getBlockRootClientId,
getBlockListSettings,
} = select( 'core/block-editor' );

const selectedBlockClientIds = getSelectedBlockClientIds();
const blockRootClientId = getBlockRootClientId(
selectedBlockClientIds[ 0 ]
Expand All @@ -51,22 +56,50 @@ export default function BlockToolbar( { hideDragHandle } ) {
};
}, [] );

const nodeRef = useRef();
const showMovers = useShowMovers( { ref: nodeRef } );

if ( blockClientIds.length === 0 ) {
return null;
}

const shouldShowVisualToolbar = isValid && mode === 'visual';
const isMultiToolbar = blockClientIds.length > 1;

const shouldShowMovers = showMovers && hasMovers;
const classes = classnames(
'block-editor-block-toolbar',
shouldShowMovers && 'is-withMovers'
);

// TODO: Refactor to CSS styles
const forcedBlockMoverWrapperStyles = {
backgroundColor: 'white',
border: '1px solid black',
borderBottomLeftRadius: 2,
borderRight: 'none',
borderTopLeftRadius: 2,
left: -1,
position: 'absolute',
top: -1,
transition: 'all 60ms linear',
userSelect: 'none',
zIndex: -1,
// interpolated values, based on whether movers should show
pointerEvents: shouldShowMovers ? 'all' : 'none',
opacity: shouldShowMovers ? 1 : 0,
transform: shouldShowMovers ? 'translateX(-48px)' : 'translateX(0)',
};

return (
<div className="block-editor-block-toolbar">
{ hasMovers && (
<div className={ classes } ref={ nodeRef }>
<div style={ forcedBlockMoverWrapperStyles }>
<BlockMover
clientIds={ blockClientIds }
__experimentalOrientation={ moverDirection }
hideDragHandle={ hideDragHandle }
/>
) }
</div>
{ ( shouldShowVisualToolbar || isMultiToolbar ) && (
<BlockSwitcher clientIds={ blockClientIds } />
) }
Expand All @@ -86,3 +119,66 @@ export default function BlockToolbar( { hideDragHandle } ) {
</div>
);
}

function useShowMovers( { ref, debounceTimeout = 300 } ) {
const [ showMovers, setShowMovers ] = useState( false );
const timeoutRef = useRef();

useEffect( () => {
const node = ref.current;
const { setTimeout, clearTimeout } = window;

const isFocusedWithin = () => {
return node.contains( document.activeElement );
};

const handleOnDocumentFocus = () => {
if ( isFocusedWithin() && ! showMovers ) {
setShowMovers( true );
}
};

const handleOnMouseMove = () => {
const timeout = timeoutRef.current;

if ( timeout && clearTimeout ) {
clearTimeout( timeout );
}
if ( ! showMovers ) {
setShowMovers( true );
}
};

const handleOnMouseLeave = () => {
if ( showMovers && ! isFocusedWithin() ) {
timeoutRef.current = setTimeout( () => {
setShowMovers( false );
}, debounceTimeout );
}
};

/**
* Events are added via DOM events (vs. React synthetic events),
* as the child React components swallow mouse events.
*/
if ( node ) {
document.addEventListener( 'focus', handleOnDocumentFocus, true );
node.addEventListener( 'mousemove', handleOnMouseMove );
node.addEventListener( 'mouseleave', handleOnMouseLeave );
}

return () => {
if ( node ) {
document.addEventListener(
'focus',
handleOnDocumentFocus,
false
);
node.removeEventListener( 'mousemove', handleOnMouseMove );
node.removeEventListener( 'mouseleave', handleOnMouseLeave );
}
};
}, [ ref, showMovers, setShowMovers, timeoutRef ] );

return showMovers;
}

0 comments on commit 79b0327

Please sign in to comment.