Skip to content

Commit

Permalink
Always show parent block selector when available.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZebulanStanphill committed Sep 23, 2020
1 parent f543ee9 commit 265c149
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 104 deletions.
24 changes: 10 additions & 14 deletions packages/block-editor/src/components/block-parent-selector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,18 @@ export default function BlockParentSelector() {

if ( firstParentClientId !== undefined ) {
return (
<div
<ToolbarButton
className="block-editor-block-parent-selector"
onClick={ () => selectBlock( firstParentClientId ) }
label={ sprintf(
/* translators: %s: Name of the block's parent. */
__( 'Select parent (%s)' ),
parentBlockType.title
) }
showTooltip
icon={ <BlockIcon icon={ parentBlockType.icon } /> }
key={ firstParentClientId }
>
<ToolbarButton
className="block-editor-block-parent-selector__button"
onClick={ () => selectBlock( firstParentClientId ) }
label={ sprintf(
/* translators: %s: Name of the block's parent. */
__( 'Select parent (%s)' ),
parentBlockType.title
) }
showTooltip
icon={ <BlockIcon icon={ parentBlockType.icon } /> }
/>
</div>
/>
);
}

Expand Down

This file was deleted.

54 changes: 18 additions & 36 deletions packages/block-editor/src/components/block-toolbar/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { ToolbarGroup } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { useRef } from '@wordpress/element';
import { useViewportMatch } from '@wordpress/compose';
import { getBlockType, hasBlockSupport } from '@wordpress/blocks';
import { ToolbarGroup } from '@wordpress/components';

/**
* Internal dependencies
Expand All @@ -21,7 +15,7 @@ import BlockSwitcher from '../block-switcher';
import BlockControls from '../block-controls';
import BlockFormatControls from '../block-format-controls';
import BlockSettingsMenu from '../block-settings-menu';
import { useShowMoversGestures } from './utils';
import { useElementHoverFocusGestures } from './utils';
import ExpandedBlockControlsContainer from './expanded-block-controls-container';

export default function BlockToolbar( {
Expand All @@ -32,17 +26,17 @@ export default function BlockToolbar( {
blockClientIds,
blockClientId,
blockType,
hasFixedToolbar,
hasParent,
isValid,
isVisual,
} = useSelect( ( select ) => {
const {
getBlockName,
getBlockMode,
getBlockParents,
getSelectedBlockClientIds,
isBlockValid,
getBlockRootClientId,
getSettings,
} = select( 'core/block-editor' );
const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
Expand All @@ -54,8 +48,8 @@ export default function BlockToolbar( {
blockType:
selectedBlockClientId &&
getBlockType( getBlockName( selectedBlockClientId ) ),
hasFixedToolbar: getSettings().hasFixedToolbar,
rootClientId: blockRootClientId,
hasParent: getBlockParents( selectedBlockClientId ).length > 0,
isValid: selectedBlockClientIds.every( ( id ) =>
isBlockValid( id )
),
Expand All @@ -68,50 +62,38 @@ export default function BlockToolbar( {
const { toggleBlockHighlight } = useDispatch( 'core/block-editor' );
const nodeRef = useRef();

const { showMovers, gestures: showMoversGestures } = useShowMoversGestures(
{
ref: nodeRef,
onChange( isFocused ) {
toggleBlockHighlight( blockClientId, isFocused );
},
}
);

const displayHeaderToolbar =
useViewportMatch( 'medium', '<' ) || hasFixedToolbar;
const showBlockHighlightGestures = useElementHoverFocusGestures( {
ref: nodeRef,
onChange( isFocused ) {
toggleBlockHighlight( blockClientId, isFocused );
},
} );

if ( blockType ) {
if ( ! hasBlockSupport( blockType, '__experimentalToolbar', true ) ) {
return null;
}
}

const shouldShowMovers = displayHeaderToolbar || showMovers;

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

const shouldShowVisualToolbar = isValid && isVisual;
const isMultiToolbar = blockClientIds.length > 1;

const classes = classnames(
'block-editor-block-toolbar',
shouldShowMovers && 'is-showing-movers'
);

const Wrapper = __experimentalExpandedControl
? ExpandedBlockControlsContainer
: 'div';

return (
<Wrapper className={ classes }>
<div ref={ nodeRef } { ...showMoversGestures }>
{ ! isMultiToolbar && (
<div className="block-editor-block-toolbar__block-parent-selector-wrapper">
<BlockParentSelector clientIds={ blockClientIds } />
</div>
) }
<Wrapper className="block-editor-block-toolbar">
{ hasParent && ! isMultiToolbar && (
<ToolbarGroup className="block-editor-block-toolbar__block-parent-selector-wrapper">
<BlockParentSelector clientIds={ blockClientIds } />
</ToolbarGroup>
) }
<div ref={ nodeRef } { ...showBlockHighlightGestures }>
{ ( shouldShowVisualToolbar || isMultiToolbar ) && (
<ToolbarGroup className="block-editor-block-toolbar__block-controls">
<BlockSwitcher clientIds={ blockClientIds } />
Expand Down
14 changes: 0 additions & 14 deletions packages/block-editor/src/components/block-toolbar/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,6 @@
}

.block-editor-block-toolbar__block-parent-selector-wrapper {
position: absolute;
top: -1px;
left: -1px;
opacity: 0;
transition: all 60ms linear;
z-index: -1; // This makes it slide out from underneath the toolbar.

@include reduce-motion("transition");

.is-showing-movers & {
opacity: 1;
transform: translateY(-($block-toolbar-height + $grid-unit-15));
}

// Hide the Parent button in Top Toolbar mode.
.edit-post-header-toolbar__block-toolbar & {
display: none;
Expand Down
57 changes: 29 additions & 28 deletions packages/block-editor/src/components/block-toolbar/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,28 @@ const { clearTimeout, setTimeout } = window;
const DEBOUNCE_TIMEOUT = 200;

/**
* Hook that creates a showMover state, as well as debounced show/hide callbacks.
* Hook that creates debounced activate/deactivate callbacks.
*
* @param {Object} props Component props.
* @param {Object} props.ref Element reference.
* @param {boolean} props.isFocused Whether the component has current focus.
* @param {number} [props.debounceTimeout=250] Debounce timeout in milliseconds.
* @param {boolean} props.isFocused Whether the component has
* current focus.
* @param {number} [props.debounceTimeout=250] Debounce timeout in
* milliseconds.
* @param {Function} [props.onChange=noop] Callback function.
*/
export function useDebouncedShowMovers( {
export function useDebouncedActivateCallbacks( {
ref,
isFocused,
debounceTimeout = DEBOUNCE_TIMEOUT,
onChange = noop,
} ) {
const [ showMovers, setShowMovers ] = useState( false );
const [ active, setActive ] = useState( false );
const timeoutRef = useRef();

const handleOnChange = ( nextIsFocused ) => {
if ( ref?.current ) {
setShowMovers( nextIsFocused );
setActive( nextIsFocused );
}

onChange( nextIsFocused );
Expand All @@ -56,19 +58,19 @@ export function useDebouncedShowMovers( {
}
};

const debouncedShowMovers = ( event ) => {
const debouncedActivate = ( event ) => {
if ( event ) {
event.stopPropagation();
}

clearTimeoutRef();

if ( ! showMovers ) {
if ( ! active ) {
handleOnChange( true );
}
};

const debouncedHideMovers = ( event ) => {
const debouncedDeactivate = ( event ) => {
if ( event ) {
event.stopPropagation();
}
Expand All @@ -85,32 +87,34 @@ export function useDebouncedShowMovers( {
useEffect( () => () => clearTimeoutRef(), [] );

return {
showMovers,
debouncedShowMovers,
debouncedHideMovers,
debouncedActivate,
debouncedDeactivate,
};
}

/**
* Hook that provides a showMovers state and gesture events for DOM elements
* that interact with the showMovers state.
* Hook that provides hover/focus gesture events for a given DOM element.
*
* @param {Object} props Component props.
* @param {Object} props.ref Element reference.
* @param {number} [props.debounceTimeout=250] Debounce timeout in milliseconds.
* @param {Function} [props.onChange=noop] Callback function.
*/
export function useShowMoversGestures( {
export function useElementHoverFocusGestures( {
ref,
debounceTimeout = DEBOUNCE_TIMEOUT,
onChange = noop,
} ) {
const [ isFocused, setIsFocused ] = useState( false );
const {
showMovers,
debouncedShowMovers,
debouncedHideMovers,
} = useDebouncedShowMovers( { ref, debounceTimeout, isFocused, onChange } );
debouncedActivate,
debouncedDeactivate,
} = useDebouncedActivateCallbacks( {
ref,
debounceTimeout,
isFocused,
onChange,
} );

const registerRef = useRef( false );

Expand All @@ -127,14 +131,14 @@ export function useShowMoversGestures( {
const handleOnFocus = () => {
if ( isFocusedWithin() ) {
setIsFocused( true );
debouncedShowMovers();
debouncedActivate();
}
};

const handleOnBlur = () => {
if ( ! isFocusedWithin() ) {
setIsFocused( false );
debouncedHideMovers();
debouncedDeactivate();
}
};

Expand All @@ -158,15 +162,12 @@ export function useShowMoversGestures( {
ref,
registerRef,
setIsFocused,
debouncedShowMovers,
debouncedHideMovers,
debouncedActivate,
debouncedDeactivate,
] );

return {
showMovers,
gestures: {
onMouseMove: debouncedShowMovers,
onMouseLeave: debouncedHideMovers,
},
onMouseMove: debouncedActivate,
onMouseLeave: debouncedDeactivate,
};
}
1 change: 0 additions & 1 deletion packages/block-editor/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
@import "./components/block-mobile-toolbar/style.scss";
@import "./components/block-mover/style.scss";
@import "./components/block-navigation/style.scss";
@import "./components/block-parent-selector/style.scss";
@import "./components/block-patterns-list/style.scss";
@import "./components/block-preview/style.scss";
@import "./components/block-settings-menu/style.scss";
Expand Down

0 comments on commit 265c149

Please sign in to comment.