Skip to content

Commit

Permalink
Refactor: useBlockTools hook (#58979)
Browse files Browse the repository at this point in the history
There are times where a block is selected but no tools are available. If we don't have any tools, we don't want to show a toolbar. This commit helps unify the logic so there is a source of truth for if it will be showing or not.

* Adds a useHasBlockToolbar hook that has the logic for if the block-toolbar will render or not.
* Adds a useBlockTools hook that privately exports which block tools will be showing (block toolbar popover, fixed block toolbar, block inserter, block breadcrumb).
* Checks if any block tools are available before adding the is-collapsed class to the central toolbar area
* Removes selected block tools wrapper from DOM if no block tools available. I'm not sure if this was intentional to leave it in the DOM before, or if it was because there wasn't a reliable way of checking for it.

---------

Co-authored-by: jeryj <jeryj@git.wordpress.org>
Co-authored-by: draganescu <andraganescu@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Co-authored-by: MaggieCabrera <onemaggie@git.wordpress.org>
  • Loading branch information
5 people committed Feb 28, 2024
1 parent cca1165 commit 226b2ba
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 155 deletions.
14 changes: 3 additions & 11 deletions packages/block-editor/src/components/block-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ import { useShowHoveredOrFocusedGestures } from './utils';
import { store as blockEditorStore } from '../../store';
import __unstableBlockNameContext from './block-name-context';
import NavigableToolbar from '../navigable-toolbar';
import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls';
import Shuffle from './shuffle';

import { useHasBlockToolbar } from './use-has-block-toolbar';
/**
* Renders the block toolbar.
*
Expand Down Expand Up @@ -122,15 +121,8 @@ export function PrivateBlockToolbar( {

const isLargeViewport = ! useViewportMatch( 'medium', '<' );

const isToolbarEnabled =
blockType &&
hasBlockSupport( blockType, '__experimentalToolbar', true );
const hasAnyBlockControls = useHasAnyBlockControls();

if (
! isToolbarEnabled ||
( ! isDefaultEditingMode && ! hasAnyBlockControls )
) {
const hasBlockToolbar = useHasBlockToolbar();
if ( ! hasBlockToolbar ) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { getBlockType, hasBlockSupport } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls';

/**
* Returns true if the block toolbar should be shown.
*
* @return {boolean} Whether the block toolbar component will be rendered.
*/
export function useHasBlockToolbar() {
const hasAnyBlockControls = useHasAnyBlockControls();
return useSelect(
( select ) => {
const {
getBlockEditingMode,
getBlockName,
getSelectedBlockClientIds,
} = select( blockEditorStore );

const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
const isDefaultEditingMode =
getBlockEditingMode( selectedBlockClientId ) === 'default';
const blockType =
selectedBlockClientId &&
getBlockType( getBlockName( selectedBlockClientId ) );
const isToolbarEnabled =
blockType &&
hasBlockSupport( blockType, '__experimentalToolbar', true );

if (
! isToolbarEnabled ||
( ! isDefaultEditingMode && ! hasAnyBlockControls )
) {
return false;
}

return true;
},
[ hasAnyBlockControls ]
);
}
49 changes: 13 additions & 36 deletions packages/block-editor/src/components/block-tools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useSelect, useDispatch } from '@wordpress/data';
import { Popover } from '@wordpress/components';
import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts';
import { useRef } from '@wordpress/element';
import { isUnmodifiedDefaultBlock } from '@wordpress/blocks';

/**
* Internal dependencies
Expand All @@ -20,51 +19,27 @@ import BlockToolbarBreadcrumb from './block-toolbar-breadcrumb';
import { store as blockEditorStore } from '../../store';
import usePopoverScroll from '../block-popover/use-popover-scroll';
import ZoomOutModeInserters from './zoom-out-mode-inserters';
import { useShowBlockTools } from './use-show-block-tools';

function selector( select ) {
const {
getSelectedBlockClientId,
getFirstMultiSelectedBlockClientId,
getBlock,
getSettings,
hasMultiSelection,
__unstableGetEditorMode,
isTyping,
} = select( blockEditorStore );

const clientId =
getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId();

const { name = '', attributes = {} } = getBlock( clientId ) || {};
const editorMode = __unstableGetEditorMode();
const hasSelectedBlock = clientId && name;
const isEmptyDefaultBlock = isUnmodifiedDefaultBlock( {
name,
attributes,
} );
const _showEmptyBlockSideInserter =
clientId &&
! isTyping() &&
editorMode === 'edit' &&
isUnmodifiedDefaultBlock( { name, attributes } );
const maybeShowBreadcrumb =
hasSelectedBlock &&
! hasMultiSelection() &&
( editorMode === 'navigation' || editorMode === 'zoom-out' );

return {
clientId,
hasFixedToolbar: getSettings().hasFixedToolbar,
isTyping: isTyping(),
isZoomOutMode: editorMode === 'zoom-out',
showEmptyBlockSideInserter: _showEmptyBlockSideInserter,
showBreadcrumb: ! _showEmptyBlockSideInserter && maybeShowBreadcrumb,
showBlockToolbar:
! getSettings().hasFixedToolbar &&
! _showEmptyBlockSideInserter &&
hasSelectedBlock &&
! isEmptyDefaultBlock &&
! maybeShowBreadcrumb,
};
}

Expand All @@ -82,18 +57,20 @@ export default function BlockTools( {
__unstableContentRef,
...props
} ) {
const {
clientId,
hasFixedToolbar,
isTyping,
isZoomOutMode,
showEmptyBlockSideInserter,
showBreadcrumb,
showBlockToolbar,
} = useSelect( selector, [] );
const { clientId, hasFixedToolbar, isTyping, isZoomOutMode } = useSelect(
selector,
[]
);
const isMatch = useShortcutEventMatch();
const { getSelectedBlockClientIds, getBlockRootClientId } =
useSelect( blockEditorStore );

const {
showEmptyBlockSideInserter,
showBreadcrumb,
showBlockToolbarPopover,
} = useShowBlockTools();

const {
duplicateBlocks,
removeBlocks,
Expand Down Expand Up @@ -186,7 +163,7 @@ export default function BlockTools( {
/>
) }

{ showBlockToolbar && (
{ showBlockToolbarPopover && (
<BlockToolbarPopover
__unstableContentRef={ __unstableContentRef }
clientId={ clientId }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { isUnmodifiedDefaultBlock } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import { useHasBlockToolbar } from '../block-toolbar/use-has-block-toolbar';

/**
* Source of truth for which block tools are showing in the block editor.
*
* @return {Object} Object of which block tools will be shown.
*/
export function useShowBlockTools() {
const hasBlockToolbar = useHasBlockToolbar();

return useSelect(
( select ) => {
const {
getSelectedBlockClientId,
getFirstMultiSelectedBlockClientId,
getBlock,
getSettings,
hasMultiSelection,
__unstableGetEditorMode,
isTyping,
} = select( blockEditorStore );

const clientId =
getSelectedBlockClientId() ||
getFirstMultiSelectedBlockClientId();

const { name = '', attributes = {} } = getBlock( clientId ) || {};
const editorMode = __unstableGetEditorMode();
const hasSelectedBlock = clientId && name;
const isEmptyDefaultBlock = isUnmodifiedDefaultBlock( {
name,
attributes,
} );
const _showEmptyBlockSideInserter =
clientId &&
! isTyping() &&
editorMode === 'edit' &&
isUnmodifiedDefaultBlock( { name, attributes } );
const maybeShowBreadcrumb =
hasSelectedBlock &&
! hasMultiSelection() &&
( editorMode === 'navigation' || editorMode === 'zoom-out' );

return {
showEmptyBlockSideInserter: _showEmptyBlockSideInserter,
showBreadcrumb:
! _showEmptyBlockSideInserter && maybeShowBreadcrumb,
showBlockToolbarPopover:
hasBlockToolbar &&
! getSettings().hasFixedToolbar &&
! _showEmptyBlockSideInserter &&
hasSelectedBlock &&
! isEmptyDefaultBlock &&
! maybeShowBreadcrumb,
showFixedToolbar:
editorMode !== 'zoom-out' &&
hasBlockToolbar &&
getSettings().hasFixedToolbar,
};
},
[ hasBlockToolbar ]
);
}
4 changes: 2 additions & 2 deletions packages/block-editor/src/private-apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ComposedPrivateInserter as PrivateInserter } from './components/inserte
import { default as PrivateQuickInserter } from './components/inserter/quick-inserter';
import { PrivateListView } from './components/list-view';
import BlockInfo from './components/block-info-slot-fill';
import { useCanBlockToolbarBeFocused } from './utils/use-can-block-toolbar-be-focused';
import { useShowBlockTools } from './components/block-tools/use-show-block-tools';
import { cleanEmptyObject, useStyleOverride } from './hooks/utils';
import BlockQuickNavigation from './components/block-quick-navigation';
import { LayoutStyle } from './components/block-list/layout';
Expand Down Expand Up @@ -44,7 +44,7 @@ lock( privateApis, {
PrivateListView,
ResizableBoxPopover,
BlockInfo,
useCanBlockToolbarBeFocused,
useShowBlockTools,
cleanEmptyObject,
useStyleOverride,
BlockQuickNavigation,
Expand Down

This file was deleted.

Loading

0 comments on commit 226b2ba

Please sign in to comment.