Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor <BlockToolbar /> #56335

Merged
merged 51 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
41a3971
Rename <SelectedBlockTools /> to <BlockToolbarPopover />
jeryj Nov 20, 2023
7169a95
Refactor commit: BlockContextualToolbar returns BlockToolbar directly
jeryj Nov 20, 2023
d54573c
Replace private <BlockContextualToolbar /> usage with public <BlockTo…
jeryj Nov 20, 2023
92b4682
Add notes. Name BlockToolbar props directly.
jeryj Nov 21, 2023
62c68e8
Remove unnecessary blockClientId check
jeryj Nov 21, 2023
f0321b2
Pass variant into <BlockToolbar />
jeryj Nov 21, 2023
3096fa0
Hide drag handle for fixed toolbars
jeryj Nov 22, 2023
08d3433
Large refactor of BlockToolbar rendering flow.
jeryj Nov 22, 2023
548cf4a
Only render BlockToolsPopover if block has been modified
jeryj Nov 22, 2023
c493c4c
Only use block popover on large screens
jeryj Nov 22, 2023
69ab86e
Remove unused showEmptyBlockSideInserter props
jeryj Nov 22, 2023
af2d5ea
Fix focus toolbar shortcut when breadcrumb and toolbar are both in DOM
jeryj Nov 22, 2023
65eacfb
Cleanup Block Popover comments
jeryj Nov 29, 2023
1f2b8bc
Deprecate focusOnMount
jeryj Nov 29, 2023
4198787
Remove shouldUseKeyboardFocusShortcut prop from use in BlockToolbar
jeryj Nov 29, 2023
109b1a0
Add __experimentalBlockToolbarDisplay prop to BlockTools and implemen…
jeryj Nov 29, 2023
f10abb8
Temporarily add isFixed prop back to sticky toolbar
jeryj Nov 29, 2023
9399a32
Use __experimentalBlockToolbarDisplay in Edit Widgets BlockTools
jeryj Nov 29, 2023
f66d417
Fix incorrect if statement for block tools and add comment
jeryj Nov 29, 2023
464b8ba
Use __experimentalBlockToolbarDisplay for widgets customizer
jeryj Nov 29, 2023
5181df3
Remove isFixed from BlockToolbar component
jeryj Nov 29, 2023
9fb88a6
Update is-typing e2e tests
jeryj Nov 30, 2023
ae4c062
Update storybook examples to use __experimentalBlockToolbarDisplay
jeryj Nov 30, 2023
4ac80ee
Hide block toolbar popover when typing
jeryj Nov 30, 2023
ef72458
Use sticky toolbar on customize widget until small screen breakpoint
jeryj Nov 30, 2023
3e16898
Edit Post: hasFixedToolbar = do not render the <BlockToolbar /> withi…
jeryj Dec 1, 2023
afca15c
Implement hasFixedToolbar setting off isLargeViewport for Widgets Editor
jeryj Dec 1, 2023
9472b35
Modify block toolbar border css to have fewer overrides
jeryj Dec 1, 2023
b2ba337
Update Storybook examples
jeryj Dec 1, 2023
91cf32f
Implemenet customize-widget toolbar modes
jeryj Dec 1, 2023
60fd0e8
Implement edit site toolbar modes
jeryj Dec 1, 2023
e7fd68b
Add docs to the BlockToolbar
jeryj Dec 1, 2023
972ce93
Add hideDragHandle and unstyled variant props to fixed toolbars
jeryj Dec 1, 2023
df1efbe
Clarify focusOnMount deprecation comments
jeryj Dec 4, 2023
ed37de4
Remove small white underline from parent block button
jeryj Dec 4, 2023
cdeca82
Set variant=unstyled as default value for BlockToolbar
jeryj Dec 4, 2023
04b42a1
Fix error in variant name
jeryj Dec 4, 2023
e842262
Remove deleted scss file from build
jeryj Dec 4, 2023
c74e1c5
Switch BlockToolbar to named function
jeryj Dec 5, 2023
d84f0fe
Deprecate focusOnMount in NavigableToolbar README
jeryj Dec 5, 2023
4d954bd
Show icon label toolbar fixes
jeryj Dec 5, 2023
533f71b
Block toolbar show-icon-label css fixes
jeryj Dec 5, 2023
a3511a2
Top toolbar css fixes
jeryj Dec 5, 2023
2dbc7d9
Revert BlockToolbarPopover to mount/unmount instead of show/hide via CSS
jeryj Dec 6, 2023
78fe591
Fix mistake around unlocking PrivateBlockToolbar within same package
jeryj Dec 7, 2023
528665a
Update is-typing test to check for toBeHidden and toBeVisible
jeryj Dec 7, 2023
d78f373
Remove unused .is-hidden from CSS show/hide toolbar revert
jeryj Dec 7, 2023
316de06
Refactor to isDefaultEditingMode
jeryj Dec 7, 2023
794bd7e
Refactor showParentSelector and shouldShowVisualToolbar
jeryj Dec 7, 2023
0dd53fa
Refactor names and selector return in block tools
jeryj Dec 7, 2023
58afab9
Remove unnecessary flex-shrink from fixed toolbar
jeryj Dec 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,18 @@ _Returns_

### BlockToolbar

Renders the block toolbar.

_Related_

- <https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-toolbar/README.md>

_Parameters_

- _props_ `Object`: Components props.
- _props.hideDragHandle_ `boolean`: Show or hide the Drag Handle for drag and drop functionality.
- _props.variant_ `string`: Style variant of the toolbar, also passed to the Dropdowns rendered from Block Toolbar Buttons.

### BlockTools

Renders block tools (the block toolbar, select/navigation mode toolbar, the insertion point and a slot for the inline rich text toolbar). Must be wrapped around the block content and editor styles wrapper or iframe.
Expand Down

This file was deleted.

275 changes: 180 additions & 95 deletions packages/block-editor/src/components/block-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { useRef } from '@wordpress/element';
import { useViewportMatch } from '@wordpress/compose';
Expand All @@ -32,38 +33,82 @@ import BlockEditVisuallyButton from '../block-edit-visually-button';
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';

const BlockToolbar = ( { hideDragHandle } ) => {
const { blockClientIds, blockType, isValid, isVisual, blockEditingMode } =
useSelect( ( select ) => {
const {
getBlockName,
getBlockMode,
getSelectedBlockClientIds,
isBlockValid,
getBlockRootClientId,
getBlockEditingMode,
} = select( blockEditorStore );
const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
const blockRootClientId = getBlockRootClientId(
selectedBlockClientId
);
return {
blockClientIds: selectedBlockClientIds,
blockType:
selectedBlockClientId &&
getBlockType( getBlockName( selectedBlockClientId ) ),
rootClientId: blockRootClientId,
isValid: selectedBlockClientIds.every( ( id ) =>
isBlockValid( id )
),
isVisual: selectedBlockClientIds.every(
( id ) => getBlockMode( id ) === 'visual'
),
blockEditingMode: getBlockEditingMode( selectedBlockClientId ),
};
}, [] );
/**
* Renders the block toolbar.
*
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-toolbar/README.md
*
* @param {Object} props Components props.
* @param {boolean} props.hideDragHandle Show or hide the Drag Handle for drag and drop functionality.
* @param {boolean} props.focusOnMount Focus the toolbar when mounted.
* @param {number} props.__experimentalInitialIndex The initial index of the toolbar item to focus.
* @param {Function} props.__experimentalOnIndexChange Callback function to be called when the index of the focused toolbar item changes.
* @param {string} props.variant Style variant of the toolbar, also passed to the Dropdowns rendered from Block Toolbar Buttons.
*/
export function PrivateBlockToolbar( {
hideDragHandle,
focusOnMount,
__experimentalInitialIndex,
__experimentalOnIndexChange,
jeryj marked this conversation as resolved.
Show resolved Hide resolved
variant = 'unstyled',
} ) {
const {
blockClientId,
blockClientIds,
isDefaultEditingMode,
blockType,
shouldShowVisualToolbar,
showParentSelector,
} = useSelect( ( select ) => {
const {
getBlockName,
getBlockMode,
getBlockParents,
getSelectedBlockClientIds,
isBlockValid,
getBlockRootClientId,
getBlockEditingMode,
} = select( blockEditorStore );
const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
const blockRootClientId = getBlockRootClientId( selectedBlockClientId );
const parents = getBlockParents( selectedBlockClientId );
const firstParentClientId = parents[ parents.length - 1 ];
const parentBlockName = getBlockName( firstParentClientId );
const parentBlockType = getBlockType( parentBlockName );
const _isDefaultEditingMode =
getBlockEditingMode( selectedBlockClientId ) === 'default';
const isValid = selectedBlockClientIds.every( ( id ) =>
isBlockValid( id )
);
const isVisual = selectedBlockClientIds.every(
( id ) => getBlockMode( id ) === 'visual'
);
return {
blockClientId: selectedBlockClientId,
blockClientIds: selectedBlockClientIds,
isDefaultEditingMode: _isDefaultEditingMode,
blockType:
selectedBlockClientId &&
getBlockType( getBlockName( selectedBlockClientId ) ),

shouldShowVisualToolbar: isValid && isVisual,
rootClientId: blockRootClientId,
showParentSelector:
parentBlockType &&
getBlockEditingMode( firstParentClientId ) === 'default' &&
hasBlockSupport(
parentBlockType,
'__experimentalParentSelector',
true
) &&
selectedBlockClientIds.length === 1 &&
_isDefaultEditingMode,
};
}, [] );

const toolbarWrapperRef = useRef( null );

Expand All @@ -76,86 +121,126 @@ const BlockToolbar = ( { hideDragHandle } ) => {

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

if ( blockType ) {
if ( ! hasBlockSupport( blockType, '__experimentalToolbar', true ) ) {
return null;
}
}
const isToolbarEnabled =
blockType &&
hasBlockSupport( blockType, '__experimentalToolbar', true );
const hasAnyBlockControls = useHasAnyBlockControls();

if ( blockClientIds.length === 0 ) {
if (
! isToolbarEnabled ||
( ! isDefaultEditingMode && ! hasAnyBlockControls )
) {
return null;
}

const shouldShowVisualToolbar = isValid && isVisual;
const isMultiToolbar = blockClientIds.length > 1;
const isSynced =
isReusableBlock( blockType ) || isTemplatePart( blockType );

const classes = classnames( 'block-editor-block-toolbar', {
// Shifts the toolbar to make room for the parent block selector.
const classes = classnames( 'block-editor-block-contextual-toolbar', {
'has-parent': showParentSelector,
} );

const innerClasses = classnames( 'block-editor-block-toolbar', {
'is-synced': isSynced,
} );

return (
<div className={ classes } ref={ toolbarWrapperRef }>
{ ! isMultiToolbar &&
isLargeViewport &&
blockEditingMode === 'default' && <BlockParentSelector /> }
{ ( shouldShowVisualToolbar || isMultiToolbar ) &&
blockEditingMode === 'default' && (
<div ref={ nodeRef } { ...showHoveredOrFocusedGestures }>
<ToolbarGroup className="block-editor-block-toolbar__block-controls">
<BlockSwitcher clientIds={ blockClientIds } />
{ ! isMultiToolbar && (
<BlockLockToolbar
clientId={ blockClientIds[ 0 ] }
wrapperRef={ toolbarWrapperRef }
<NavigableToolbar
focusEditorOnEscape
className={ classes }
/* translators: accessibility text for the block toolbar */
aria-label={ __( 'Block tools' ) }
// The variant is applied as "toolbar" when undefined, which is the black border style of the dropdown from the toolbar popover.
variant={ variant === 'toolbar' ? undefined : variant }
focusOnMount={ focusOnMount }
__experimentalInitialIndex={ __experimentalInitialIndex }
__experimentalOnIndexChange={ __experimentalOnIndexChange }
// Resets the index whenever the active block changes so
// this is not persisted. See https://github.com/WordPress/gutenberg/pull/25760#issuecomment-717906169
key={ blockClientId }
>
<div ref={ toolbarWrapperRef } className={ innerClasses }>
{ ! isMultiToolbar &&
isLargeViewport &&
isDefaultEditingMode && <BlockParentSelector /> }
{ ( shouldShowVisualToolbar || isMultiToolbar ) &&
isDefaultEditingMode && (
<div
ref={ nodeRef }
{ ...showHoveredOrFocusedGestures }
>
<ToolbarGroup className="block-editor-block-toolbar__block-controls">
<BlockSwitcher clientIds={ blockClientIds } />
{ ! isMultiToolbar && (
<BlockLockToolbar
clientId={ blockClientIds[ 0 ] }
wrapperRef={ toolbarWrapperRef }
/>
) }
<BlockMover
clientIds={ blockClientIds }
hideDragHandle={ hideDragHandle }
/>
) }
<BlockMover
clientIds={ blockClientIds }
hideDragHandle={ hideDragHandle }
/>
</ToolbarGroup>
</div>
</ToolbarGroup>
</div>
) }
{ shouldShowVisualToolbar && isMultiToolbar && (
<BlockGroupToolbar />
) }
{ shouldShowVisualToolbar && (
<>
<BlockControls.Slot
group="parent"
className="block-editor-block-toolbar__slot"
/>
<BlockControls.Slot
group="block"
className="block-editor-block-toolbar__slot"
/>
<BlockControls.Slot className="block-editor-block-toolbar__slot" />
<BlockControls.Slot
group="inline"
className="block-editor-block-toolbar__slot"
/>
<BlockControls.Slot
group="other"
className="block-editor-block-toolbar__slot"
/>
<__unstableBlockNameContext.Provider
value={ blockType?.name }
>
<__unstableBlockToolbarLastItem.Slot />
</__unstableBlockNameContext.Provider>
</>
) }
<BlockEditVisuallyButton clientIds={ blockClientIds } />
{ isDefaultEditingMode && (
<BlockSettingsMenu clientIds={ blockClientIds } />
) }
{ shouldShowVisualToolbar && isMultiToolbar && (
<BlockGroupToolbar />
) }
{ shouldShowVisualToolbar && (
<>
<BlockControls.Slot
group="parent"
className="block-editor-block-toolbar__slot"
/>
<BlockControls.Slot
group="block"
className="block-editor-block-toolbar__slot"
/>
<BlockControls.Slot className="block-editor-block-toolbar__slot" />
<BlockControls.Slot
group="inline"
className="block-editor-block-toolbar__slot"
/>
<BlockControls.Slot
group="other"
className="block-editor-block-toolbar__slot"
/>
<__unstableBlockNameContext.Provider
value={ blockType?.name }
>
<__unstableBlockToolbarLastItem.Slot />
</__unstableBlockNameContext.Provider>
</>
) }
<BlockEditVisuallyButton clientIds={ blockClientIds } />
{ blockEditingMode === 'default' && (
<BlockSettingsMenu clientIds={ blockClientIds } />
) }
</div>
</div>
</NavigableToolbar>
);
};
}

/**
* Renders the block toolbar.
*
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-toolbar/README.md
*
* @param {Object} props Components props.
* @param {boolean} props.hideDragHandle Show or hide the Drag Handle for drag and drop functionality.
* @param {string} props.variant Style variant of the toolbar, also passed to the Dropdowns rendered from Block Toolbar Buttons.
*/
export default BlockToolbar;
export default function BlockToolbar( { hideDragHandle, variant } ) {
return (
<PrivateBlockToolbar
hideDragHandle={ hideDragHandle }
variant={ variant }
focusOnMount={ undefined }
__experimentalInitialIndex={ undefined }
__experimentalOnIndexChange={ undefined }
/>
);
}
Loading
Loading