From 41a3971b44bcd2d7727a4d13e70875f4e59af073 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 20 Nov 2023 12:08:36 -0600 Subject: [PATCH 01/51] Rename to This is a wrapper on to turn it into a popover, so the rename helps make it clearer what the purpose of this component is. --- .../block-editor/src/components/block-tools/back-compat.js | 4 ++-- .../{selected-block-tools.js => block-toolbar-popover.js} | 2 +- packages/block-editor/src/components/block-tools/index.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename packages/block-editor/src/components/block-tools/{selected-block-tools.js => block-toolbar-popover.js} (98%) diff --git a/packages/block-editor/src/components/block-tools/back-compat.js b/packages/block-editor/src/components/block-tools/back-compat.js index 029419926e9ed5..14027760be1e6a 100644 --- a/packages/block-editor/src/components/block-tools/back-compat.js +++ b/packages/block-editor/src/components/block-tools/back-compat.js @@ -9,7 +9,7 @@ import deprecated from '@wordpress/deprecated'; * Internal dependencies */ import InsertionPoint, { InsertionPointOpenRef } from './insertion-point'; -import BlockPopover from './selected-block-tools'; +import BlockToolbarPopover from './block-toolbar-popover'; export default function BlockToolsBackCompat( { children } ) { const openRef = useContext( InsertionPointOpenRef ); @@ -28,7 +28,7 @@ export default function BlockToolsBackCompat( { children } ) { return ( - + { children } ); diff --git a/packages/block-editor/src/components/block-tools/selected-block-tools.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js similarity index 98% rename from packages/block-editor/src/components/block-tools/selected-block-tools.js rename to packages/block-editor/src/components/block-tools/block-toolbar-popover.js index dfbd3e9ba3ca3c..066eb584d4c291 100644 --- a/packages/block-editor/src/components/block-tools/selected-block-tools.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -21,7 +21,7 @@ import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; import useSelectedBlockToolProps from './use-selected-block-tool-props'; import { useShouldContextualToolbarShow } from '../../utils/use-should-contextual-toolbar-show'; -export default function SelectedBlockTools( { +export default function BlockToolbarPopover( { clientId, showEmptyBlockSideInserter, __unstableContentRef, diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index bc2729fbb15990..7c2d7ca5c3b0cd 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -16,7 +16,7 @@ import { InsertionPointOpenRef, default as InsertionPoint, } from './insertion-point'; -import SelectedBlockTools from './selected-block-tools'; +import BlockToolbarPopover from './block-toolbar-popover'; import { store as blockEditorStore } from '../../store'; import BlockContextualToolbar from './block-contextual-toolbar'; import usePopoverScroll from '../block-popover/use-popover-scroll'; @@ -192,7 +192,7 @@ export default function BlockTools( { { /* Even if the toolbar is fixed, the block popover is still needed for navigation and zoom-out mode. */ } { ! showEmptyBlockSideInserter && hasSelectedBlock && ( - From 7169a95f849b53222fe14a21ed846a7a0e8084cf Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 20 Nov 2023 12:47:41 -0600 Subject: [PATCH 02/51] Refactor commit: BlockContextualToolbar returns BlockToolbar directly --- .../src/components/block-toolbar/index.js | 241 +++++++++++------- .../block-tools/block-contextual-toolbar.js | 89 +------ 2 files changed, 155 insertions(+), 175 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 963cd8a475328a..933f492c5c35c5 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -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'; @@ -32,38 +33,70 @@ 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 ), - }; - }, [] ); +// TODO: Remove isFixed. That is a temporary prop to support the old fixed toolbar. All toolbars will be "fixed"/don't care about this distinction. +const BlockToolbar = ( { + hideDragHandle, + focusOnMount, + isFixed, + ...props +} ) => { + const { + blockClientId, + blockClientIds, + blockEditingMode, + blockType, + hasParents, + isValid, + isVisual, + 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 ); + return { + blockClientId: selectedBlockClientId, + blockClientIds: selectedBlockClientIds, + blockEditingMode: getBlockEditingMode( selectedBlockClientId ), + blockType: + selectedBlockClientId && + getBlockType( getBlockName( selectedBlockClientId ) ), + + hasParents: parents.length, + isValid: selectedBlockClientIds.every( ( id ) => + isBlockValid( id ) + ), + isVisual: selectedBlockClientIds.every( + ( id ) => getBlockMode( id ) === 'visual' + ), + rootClientId: blockRootClientId, + showParentSelector: + parentBlockType && + getBlockEditingMode( firstParentClientId ) === 'default' && + hasBlockSupport( + parentBlockType, + '__experimentalParentSelector', + true + ) && + selectedBlockClientIds.length <= 1 && + getBlockEditingMode( selectedBlockClientId ) === 'default', + }; + }, [] ); const toolbarWrapperRef = useRef( null ); @@ -76,10 +109,16 @@ 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 ( + ! isToolbarEnabled || + ( blockEditingMode !== 'default' && ! hasAnyBlockControls ) + ) { + return null; } if ( blockClientIds.length === 0 ) { @@ -91,67 +130,89 @@ const BlockToolbar = ( { hideDragHandle } ) => { 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': hasParents && showParentSelector, + 'is-fixed': isFixed, + } ); + + const innerClasses = classnames( 'block-editor-block-toolbar', { 'is-synced': isSynced, } ); return ( -
- { ! isMultiToolbar && - isLargeViewport && - blockEditingMode === 'default' && } - { ( shouldShowVisualToolbar || isMultiToolbar ) && - blockEditingMode === 'default' && ( -
- - - { ! isMultiToolbar && ( - +
+ { ! isMultiToolbar && + isLargeViewport && + blockEditingMode === 'default' && } + { ( shouldShowVisualToolbar || isMultiToolbar ) && + blockEditingMode === 'default' && ( +
+ + + { ! isMultiToolbar && ( + + ) } + - ) } - - -
+ +
+ ) } + { shouldShowVisualToolbar && isMultiToolbar && ( + + ) } + { shouldShowVisualToolbar && ( + <> + + + + + + <__unstableBlockNameContext.Provider + value={ blockType?.name } + > + <__unstableBlockToolbarLastItem.Slot /> + + + ) } + + { blockEditingMode === 'default' && ( + ) } - { shouldShowVisualToolbar && isMultiToolbar && ( - - ) } - { shouldShowVisualToolbar && ( - <> - - - - - - <__unstableBlockNameContext.Provider - value={ blockType?.name } - > - <__unstableBlockToolbarLastItem.Slot /> - - - ) } - - { blockEditingMode === 'default' && ( - - ) } -
+
+ ); }; diff --git a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js index b24a25ee60ed42..f5c2c42baac7fe 100644 --- a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js +++ b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js @@ -1,100 +1,19 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { hasBlockSupport, store as blocksStore } from '@wordpress/blocks'; -import { useSelect } from '@wordpress/data'; - /** * Internal dependencies */ -import NavigableToolbar from '../navigable-toolbar'; import BlockToolbar from '../block-toolbar'; -import { store as blockEditorStore } from '../../store'; -import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls'; export default function BlockContextualToolbar( { focusOnMount, isFixed, ...props } ) { - const { - blockType, - blockEditingMode, - hasParents, - showParentSelector, - selectedBlockClientId, - } = useSelect( ( select ) => { - const { - getBlockName, - getBlockParents, - getSelectedBlockClientIds, - getBlockEditingMode, - } = select( blockEditorStore ); - const { getBlockType } = select( blocksStore ); - const selectedBlockClientIds = getSelectedBlockClientIds(); - const _selectedBlockClientId = selectedBlockClientIds[ 0 ]; - const parents = getBlockParents( _selectedBlockClientId ); - const firstParentClientId = parents[ parents.length - 1 ]; - const parentBlockName = getBlockName( firstParentClientId ); - const parentBlockType = getBlockType( parentBlockName ); - - return { - selectedBlockClientId: _selectedBlockClientId, - blockType: - _selectedBlockClientId && - getBlockType( getBlockName( _selectedBlockClientId ) ), - blockEditingMode: getBlockEditingMode( _selectedBlockClientId ), - hasParents: parents.length, - showParentSelector: - parentBlockType && - getBlockEditingMode( firstParentClientId ) === 'default' && - hasBlockSupport( - parentBlockType, - '__experimentalParentSelector', - true - ) && - selectedBlockClientIds.length <= 1 && - getBlockEditingMode( _selectedBlockClientId ) === 'default', - }; - }, [] ); - - const isToolbarEnabled = - blockType && - hasBlockSupport( blockType, '__experimentalToolbar', true ); - const hasAnyBlockControls = useHasAnyBlockControls(); - if ( - ! isToolbarEnabled || - ( blockEditingMode !== 'default' && ! hasAnyBlockControls ) - ) { - return null; - } - - // Shifts the toolbar to make room for the parent block selector. - const classes = classnames( 'block-editor-block-contextual-toolbar', { - 'has-parent': hasParents && showParentSelector, - 'is-fixed': isFixed, - } ); - return ( - - - + /> ); } From d54573cb29fda5c351fb5aef5e363b27ed5db964 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 20 Nov 2023 12:56:44 -0600 Subject: [PATCH 03/51] Replace private usage with public --- .../block-tools/block-contextual-toolbar.js | 19 ------------------- .../block-tools/block-toolbar-popover.js | 4 ++-- .../src/components/block-tools/index.js | 4 ++-- packages/block-editor/src/private-apis.js | 2 -- .../src/components/header/index.js | 10 ++-------- .../edit-post/src/components/header/index.js | 7 ++----- .../src/components/header-edit-mode/index.js | 6 ++---- .../src/components/header/index.js | 7 ++----- 8 files changed, 12 insertions(+), 47 deletions(-) delete mode 100644 packages/block-editor/src/components/block-tools/block-contextual-toolbar.js diff --git a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js deleted file mode 100644 index f5c2c42baac7fe..00000000000000 --- a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Internal dependencies - */ -import BlockToolbar from '../block-toolbar'; - -export default function BlockContextualToolbar( { - focusOnMount, - isFixed, - ...props -} ) { - return ( - - ); -} diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index 066eb584d4c291..64e2e8802b9405 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -14,7 +14,7 @@ import { useShortcut } from '@wordpress/keyboard-shortcuts'; * Internal dependencies */ import BlockSelectionButton from './block-selection-button'; -import BlockContextualToolbar from './block-contextual-toolbar'; +import BlockToolbar from '../block-toolbar'; import { store as blockEditorStore } from '../../store'; import BlockPopover from '../block-popover'; import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; @@ -101,7 +101,7 @@ export default function BlockToolbarPopover( { { ...popoverProps } > { shouldShowContextualToolbar && ( - + ) } { showEmptyBlockSideInserter && ( diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index b1d499ae099469..9837c206487bea 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -10,7 +10,6 @@ import ResizableBoxPopover from './components/resizable-box-popover'; import { ComposedPrivateInserter as PrivateInserter } from './components/inserter'; import { PrivateListView } from './components/list-view'; import BlockInfo from './components/block-info-slot-fill'; -import BlockContextualToolbar from './components/block-tools/block-contextual-toolbar'; import { useShouldContextualToolbarShow } from './utils/use-should-contextual-toolbar-show'; import { cleanEmptyObject, useStyleOverride } from './hooks/utils'; import BlockQuickNavigation from './components/block-quick-navigation'; @@ -42,7 +41,6 @@ lock( privateApis, { PrivateListView, ResizableBoxPopover, BlockInfo, - BlockContextualToolbar, useShouldContextualToolbarShow, cleanEmptyObject, useStyleOverride, diff --git a/packages/customize-widgets/src/components/header/index.js b/packages/customize-widgets/src/components/header/index.js index 34e4573c719dd5..2109da64182d8e 100644 --- a/packages/customize-widgets/src/components/header/index.js +++ b/packages/customize-widgets/src/components/header/index.js @@ -8,10 +8,7 @@ import classnames from 'classnames'; */ import { Popover, ToolbarButton } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; -import { - NavigableToolbar, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; +import { BlockToolbar, NavigableToolbar } from '@wordpress/block-editor'; import { createPortal, useEffect, useRef, useState } from '@wordpress/element'; import { displayShortcut, isAppleOS } from '@wordpress/keycodes'; import { __, _x, isRTL } from '@wordpress/i18n'; @@ -22,9 +19,6 @@ import { plus, undo as undoIcon, redo as redoIcon } from '@wordpress/icons'; */ import Inserter from '../inserter'; import MoreMenu from '../more-menu'; -import { unlock } from '../../lock-unlock'; - -const { BlockContextualToolbar } = unlock( blockEditorPrivateApis ); function Header( { sidebar, @@ -111,7 +105,7 @@ function Header( { { isFixedToolbarActive && isLargeViewport && ( <>
- +
- + - +
- +
Date: Tue, 21 Nov 2023 11:56:37 -0600 Subject: [PATCH 04/51] Add notes. Name BlockToolbar props directly. --- .../src/components/block-toolbar/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 933f492c5c35c5..00116edf5defc1 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -36,12 +36,12 @@ import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls'; -// TODO: Remove isFixed. That is a temporary prop to support the old fixed toolbar. All toolbars will be "fixed"/don't care about this distinction. const BlockToolbar = ( { hideDragHandle, focusOnMount, - isFixed, - ...props + isFixed, // TODO: Remove isFixed. That is a temporary prop to support the old fixed toolbar. All toolbars will be "fixed"/don't care about this distinction. + __experimentalInitialIndex, + __experimentalOnIndexChange, } ) => { const { blockClientId, @@ -147,11 +147,12 @@ const BlockToolbar = ( { className={ classes } /* translators: accessibility text for the block toolbar */ aria-label={ __( 'Block tools' ) } - variant={ isFixed ? 'unstyled' : undefined } + variant={ isFixed ? 'unstyled' : undefined } // TODO: Remove this. Let this be handled by the wrapper and remove an assumed "toolbar" context from dropdowns. // 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 } - { ...props } + __experimentalInitialIndex={ __experimentalInitialIndex } + __experimentalOnIndexChange={ __experimentalOnIndexChange } >
{ ! isMultiToolbar && From 62c68e802119eb718e5de8a4c3b44f3902d2aed6 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 21 Nov 2023 11:57:01 -0600 Subject: [PATCH 05/51] Remove unnecessary blockClientId check This was already handled with isToolbarEnabled. --- packages/block-editor/src/components/block-toolbar/index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 00116edf5defc1..6f3feb6f08c038 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -121,10 +121,6 @@ const BlockToolbar = ( { return null; } - if ( blockClientIds.length === 0 ) { - return null; - } - const shouldShowVisualToolbar = isValid && isVisual; const isMultiToolbar = blockClientIds.length > 1; const isSynced = From f0321b2cd1abd3d8b8fd94ede956877693e18419 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 21 Nov 2023 13:56:10 -0600 Subject: [PATCH 06/51] Pass variant into The variant is used to style dropdown borders. All block toolbars are assumed to have a variant of "toolbar" which adds a dark black border to dropdowns. I think it's worth revisiting this idea, as the block toolbar popover styles are not assumed for all toolbars, but this is the system that's currently in place, so I'm rolling with it for now. If we could pass the variant in via the Popover instead, that would be ideal, and then remove the assumed toolbar context from the dropdowns. --- packages/block-editor/src/components/block-toolbar/index.js | 3 ++- packages/block-editor/src/components/block-tools/index.js | 2 +- packages/customize-widgets/src/components/header/index.js | 2 +- packages/edit-post/src/components/header/index.js | 2 +- packages/edit-site/src/components/header-edit-mode/index.js | 2 +- packages/edit-widgets/src/components/header/index.js | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 6f3feb6f08c038..52efa08db36184 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -42,6 +42,7 @@ const BlockToolbar = ( { isFixed, // TODO: Remove isFixed. That is a temporary prop to support the old fixed toolbar. All toolbars will be "fixed"/don't care about this distinction. __experimentalInitialIndex, __experimentalOnIndexChange, + variant, } ) => { const { blockClientId, @@ -143,7 +144,7 @@ const BlockToolbar = ( { className={ classes } /* translators: accessibility text for the block toolbar */ aria-label={ __( 'Block tools' ) } - variant={ isFixed ? 'unstyled' : undefined } // TODO: Remove this. Let this be handled by the wrapper and remove an assumed "toolbar" context from dropdowns. + variant={ variant } // 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 } diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 8ce050ac8b62b1..94b6394b0abd04 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -180,7 +180,7 @@ export default function BlockTools( { { /* If there is no slot available, such as in the standalone block editor, render within the editor */ } { ! isLargeViewport && ( // Small viewports always get a fixed toolbar - + ) } { showEmptyBlockSideInserter && ( diff --git a/packages/customize-widgets/src/components/header/index.js b/packages/customize-widgets/src/components/header/index.js index 2109da64182d8e..6d4c2e27e32b3e 100644 --- a/packages/customize-widgets/src/components/header/index.js +++ b/packages/customize-widgets/src/components/header/index.js @@ -105,7 +105,7 @@ function Header( { { isFixedToolbarActive && isLargeViewport && ( <>
- +
- +
- +
- +
Date: Wed, 22 Nov 2023 10:53:33 -0600 Subject: [PATCH 07/51] Hide drag handle for fixed toolbars --- packages/block-editor/src/components/block-tools/index.js | 2 +- packages/customize-widgets/src/components/header/index.js | 6 +++++- packages/edit-post/src/components/header/index.js | 6 +++++- packages/edit-site/src/components/header-edit-mode/index.js | 6 +++++- packages/edit-widgets/src/components/header/index.js | 6 +++++- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 94b6394b0abd04..85d46831dc52fb 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -180,7 +180,7 @@ export default function BlockTools( { { /* If there is no slot available, such as in the standalone block editor, render within the editor */ } { ! isLargeViewport && ( // Small viewports always get a fixed toolbar - + ) } { showEmptyBlockSideInserter && ( diff --git a/packages/customize-widgets/src/components/header/index.js b/packages/customize-widgets/src/components/header/index.js index 6d4c2e27e32b3e..5bd746715de998 100644 --- a/packages/customize-widgets/src/components/header/index.js +++ b/packages/customize-widgets/src/components/header/index.js @@ -105,7 +105,11 @@ function Header( { { isFixedToolbarActive && isLargeViewport && ( <>
- +
- + - +
- +
Date: Wed, 22 Nov 2023 13:51:15 -0600 Subject: [PATCH 08/51] Large refactor of BlockToolbar rendering flow. - Split out Block Toolbar Breadcrumb and Block Toolbar Popover The Block Toolbar Popover and Block Toolbar Breadcrumb did not rely on each other and the logic of each other was intertwined in an unhelpful way. Split these out to have more control over the rendering of the toolbar. - Remove initialIndex and focusing on mount for BlockToolbar Now the BlockToolbar is always rendered if there are block tools for it, but in the case of the popover, it is hidden via CSS if we don't want it to show. This makes the logic simpler, removes quite a bit of code, and reduces renders. We now get the initial focus on mount index "for free" because we never unmount the component. The index resets automatically when the block changes. - --- .../src/components/block-popover/style.scss | 5 + .../src/components/block-toolbar/index.js | 13 +- .../block-tools/block-toolbar-breadcrumb.js | 77 ++++++++++++ .../block-tools/block-toolbar-popover.js | 116 +++--------------- .../src/components/block-tools/index.js | 15 ++- .../src/components/navigable-toolbar/index.js | 54 +------- 6 files changed, 124 insertions(+), 156 deletions(-) create mode 100644 packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js diff --git a/packages/block-editor/src/components/block-popover/style.scss b/packages/block-editor/src/components/block-popover/style.scss index e393e77c63b056..347053f628b8a9 100644 --- a/packages/block-editor/src/components/block-popover/style.scss +++ b/packages/block-editor/src/components/block-popover/style.scss @@ -22,6 +22,11 @@ pointer-events: all; } } + + &.is-hidden { + opacity: 0; + z-index: -1; + } } .components-popover.block-editor-block-popover__inbetween { diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 52efa08db36184..9eea40e89b3b4e 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -15,6 +15,7 @@ import { hasBlockSupport, isReusableBlock, isTemplatePart, + isUnmodifiedDefaultBlock, } from '@wordpress/blocks'; import { ToolbarGroup } from '@wordpress/components'; @@ -38,10 +39,7 @@ import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls const BlockToolbar = ( { hideDragHandle, - focusOnMount, isFixed, // TODO: Remove isFixed. That is a temporary prop to support the old fixed toolbar. All toolbars will be "fixed"/don't care about this distinction. - __experimentalInitialIndex, - __experimentalOnIndexChange, variant, } ) => { const { @@ -50,11 +48,13 @@ const BlockToolbar = ( { blockEditingMode, blockType, hasParents, + isEmptyDefaultBlock, isValid, isVisual, showParentSelector, } = useSelect( ( select ) => { const { + getBlock, getBlockName, getBlockMode, getBlockParents, @@ -79,6 +79,9 @@ const BlockToolbar = ( { getBlockType( getBlockName( selectedBlockClientId ) ), hasParents: parents.length, + isEmptyDefaultBlock: isUnmodifiedDefaultBlock( + getBlock( selectedBlockClientId ) || {} + ), isValid: selectedBlockClientIds.every( ( id ) => isBlockValid( id ) ), @@ -116,6 +119,7 @@ const BlockToolbar = ( { const hasAnyBlockControls = useHasAnyBlockControls(); if ( + isEmptyDefaultBlock || ! isToolbarEnabled || ( blockEditingMode !== 'default' && ! hasAnyBlockControls ) ) { @@ -139,7 +143,6 @@ const BlockToolbar = ( { return (
{ ! isMultiToolbar && diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js b/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js new file mode 100644 index 00000000000000..0fe8fbb8ba48ba --- /dev/null +++ b/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js @@ -0,0 +1,77 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import BlockSelectionButton from './block-selection-button'; +import { store as blockEditorStore } from '../../store'; +import BlockPopover from '../block-popover'; +import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; +import useSelectedBlockToolProps from './use-selected-block-tool-props'; + +export default function BlockToolbarBreadcrumb( { + clientId, + showEmptyBlockSideInserter, + __unstableContentRef, +} ) { + const { + capturingClientId, + isInsertionPointVisible, + lastClientId, + rootClientId, + } = useSelectedBlockToolProps( clientId ); + + const { shouldShowBreadcrumb } = useSelect( ( select ) => { + const { hasMultiSelection, __unstableGetEditorMode } = + select( blockEditorStore ); + + const editorMode = __unstableGetEditorMode(); + + return { + shouldShowBreadcrumb: + ! hasMultiSelection() && + ( editorMode === 'navigation' || editorMode === 'zoom-out' ), + }; + }, [] ); + + const popoverProps = useBlockToolbarPopoverProps( { + contentElement: __unstableContentRef?.current, + clientId, + } ); + + if ( showEmptyBlockSideInserter ) { + return null; + } + + if ( shouldShowBreadcrumb ) { + return ( + + + + ); + } + + return null; +} diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index 64e2e8802b9405..10adc5cff30c0b 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -3,19 +3,10 @@ */ import classnames from 'classnames'; -/** - * WordPress dependencies - */ -import { useRef, useEffect } from '@wordpress/element'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { useShortcut } from '@wordpress/keyboard-shortcuts'; - /** * Internal dependencies */ -import BlockSelectionButton from './block-selection-button'; import BlockToolbar from '../block-toolbar'; -import { store as blockEditorStore } from '../../store'; import BlockPopover from '../block-popover'; import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; import useSelectedBlockToolProps from './use-selected-block-tool-props'; @@ -26,102 +17,33 @@ export default function BlockToolbarPopover( { showEmptyBlockSideInserter, __unstableContentRef, } ) { - const { - capturingClientId, - isInsertionPointVisible, - lastClientId, - rootClientId, - } = useSelectedBlockToolProps( clientId ); - - const { shouldShowBreadcrumb } = useSelect( ( select ) => { - const { hasMultiSelection, __unstableGetEditorMode } = - select( blockEditorStore ); - - const editorMode = __unstableGetEditorMode(); - - return { - shouldShowBreadcrumb: - ! hasMultiSelection() && - ( editorMode === 'navigation' || editorMode === 'zoom-out' ), - }; - }, [] ); - - const isToolbarForced = useRef( false ); - const { shouldShowContextualToolbar, canFocusHiddenToolbar } = - useShouldContextualToolbarShow(); - - const { stopTyping } = useDispatch( blockEditorStore ); - - useShortcut( - 'core/block-editor/focus-toolbar', - () => { - isToolbarForced.current = true; - stopTyping( true ); - }, - { - isDisabled: ! canFocusHiddenToolbar, - } - ); - - useEffect( () => { - isToolbarForced.current = false; - } ); - - // Stores the active toolbar item index so the block toolbar can return focus - // to it when re-mounting. - const initialToolbarItemIndexRef = useRef(); - - useEffect( () => { - // Resets the index whenever the active block changes so this is not - // persisted. See https://github.com/WordPress/gutenberg/pull/25760#issuecomment-717906169 - initialToolbarItemIndexRef.current = undefined; - }, [ clientId ] ); + const { capturingClientId, isInsertionPointVisible, lastClientId } = + useSelectedBlockToolProps( clientId ); const popoverProps = useBlockToolbarPopoverProps( { contentElement: __unstableContentRef?.current, clientId, } ); + const { shouldShowContextualToolbar } = useShouldContextualToolbarShow(); + if ( showEmptyBlockSideInserter ) { return null; } - if ( shouldShowBreadcrumb || shouldShowContextualToolbar ) { - return ( - - { shouldShowContextualToolbar && ( - { - initialToolbarItemIndexRef.current = index; - } } - /> - ) } - { shouldShowBreadcrumb && ( - - ) } - - ); - } - - return null; + // There shouldn't be an idea of focus on mount. It's just "Does the shortcut work or not". If there are block tools it can be focused. If the block tools have been accessed, the same tabindex will be persisted until it is remounted via a block change. + return ( + + + + ); } diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 85d46831dc52fb..e5217968e76701 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -17,6 +17,7 @@ import { default as InsertionPoint, } from './insertion-point'; import BlockToolbarPopover from './block-toolbar-popover'; +import BlockToolbarBreadcrumb from './block-toolbar-breadcrumb'; import { store as blockEditorStore } from '../../store'; import BlockToolbar from '../block-toolbar'; import usePopoverScroll from '../block-popover/use-popover-scroll'; @@ -189,10 +190,18 @@ export default function BlockTools( { clientId={ clientId } /> ) } - { /* Even if the toolbar is fixed, the block popover is still - needed for navigation and zoom-out mode. */ } + + { ! hasFixedToolbar && + ! showEmptyBlockSideInserter && + hasSelectedBlock && ( + + ) } + { ! showEmptyBlockSideInserter && hasSelectedBlock && ( - diff --git a/packages/block-editor/src/components/navigable-toolbar/index.js b/packages/block-editor/src/components/navigable-toolbar/index.js index fe216e1058f6f0..7a56ad1835b93d 100644 --- a/packages/block-editor/src/components/navigable-toolbar/index.js +++ b/packages/block-editor/src/components/navigable-toolbar/index.js @@ -9,7 +9,7 @@ import { useEffect, useCallback, } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; import { focus } from '@wordpress/dom'; import { useShortcut } from '@wordpress/keyboard-shortcuts'; @@ -25,14 +25,6 @@ function hasOnlyToolbarItem( elements ) { return ! elements.some( ( element ) => ! ( dataProp in element.dataset ) ); } -function getAllToolbarItemsIn( container ) { - return Array.from( container.querySelectorAll( '[data-toolbar-item]' ) ); -} - -function hasFocusWithin( container ) { - return container.contains( container.ownerDocument.activeElement ); -} - function focusFirstTabbableIn( container ) { const [ firstTabbable ] = focus.tabbable.find( container ); @@ -103,14 +95,12 @@ function useToolbarFocus( { toolbarRef, focusOnMount, isAccessibleToolbar, - defaultIndex, - onIndexChange, shouldUseKeyboardFocusShortcut, focusEditorOnEscape, } ) { // Make sure we don't use modified versions of this prop. const [ initialFocusOnMount ] = useState( focusOnMount ); - const [ initialIndex ] = useState( defaultIndex ); + const { stopTyping } = useDispatch( blockEditorStore ); const focusToolbar = useCallback( () => { focusFirstTabbableIn( toolbarRef.current ); @@ -118,6 +108,7 @@ function useToolbarFocus( { const focusToolbarViaShortcut = () => { if ( shouldUseKeyboardFocusShortcut ) { + stopTyping( true ); // This matches the behavior of the Tab/Escape observe typing to stopTyping. Should we add this shortcut there? focusToolbar(); } }; @@ -125,45 +116,13 @@ function useToolbarFocus( { // Focus on toolbar when pressing alt+F10 when the toolbar is visible. useShortcut( 'core/block-editor/focus-toolbar', focusToolbarViaShortcut ); + // Unused in codebase. Do we need to keep it for backwards compatability? useEffect( () => { if ( initialFocusOnMount ) { focusToolbar(); } }, [ isAccessibleToolbar, initialFocusOnMount, focusToolbar ] ); - useEffect( () => { - // Store ref so we have access on useEffect cleanup: https://legacy.reactjs.org/blog/2020/08/10/react-v17-rc.html#effect-cleanup-timing - const navigableToolbarRef = toolbarRef.current; - // If initialIndex is passed, we focus on that toolbar item when the - // toolbar gets mounted and initial focus is not forced. - // We have to wait for the next browser paint because block controls aren't - // rendered right away when the toolbar gets mounted. - let raf = 0; - if ( ! initialFocusOnMount ) { - raf = window.requestAnimationFrame( () => { - const items = getAllToolbarItemsIn( navigableToolbarRef ); - const index = initialIndex || 0; - if ( items[ index ] && hasFocusWithin( navigableToolbarRef ) ) { - items[ index ].focus( { - // When focusing newly mounted toolbars, - // the position of the popover is often not right on the first render - // This prevents the layout shifts when focusing the dialogs. - preventScroll: true, - } ); - } - } ); - } - return () => { - window.cancelAnimationFrame( raf ); - if ( ! onIndexChange || ! navigableToolbarRef ) return; - // When the toolbar element is unmounted and onIndexChange is passed, we - // pass the focused toolbar item index so it can be hydrated later. - const items = getAllToolbarItemsIn( navigableToolbarRef ); - const index = items.findIndex( ( item ) => item.tabIndex === 0 ); - onIndexChange( index ); - }; - }, [ initialIndex, initialFocusOnMount, toolbarRef ] ); - const { lastFocus } = useSelect( ( select ) => { const { getLastFocus } = select( blockEditorStore ); return { @@ -200,19 +159,14 @@ export default function NavigableToolbar( { focusOnMount, focusEditorOnEscape = false, shouldUseKeyboardFocusShortcut = true, - __experimentalInitialIndex: initialIndex, - __experimentalOnIndexChange: onIndexChange, ...props } ) { const toolbarRef = useRef(); const isAccessibleToolbar = useIsAccessibleToolbar( toolbarRef ); - useToolbarFocus( { toolbarRef, focusOnMount, isAccessibleToolbar, - defaultIndex: initialIndex, - onIndexChange, shouldUseKeyboardFocusShortcut, focusEditorOnEscape, } ); From 548cf4acfe2a660fabbc5bd2dfe554ead58ced8e Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 22 Nov 2023 14:35:37 -0600 Subject: [PATCH 09/51] Only render BlockToolsPopover if block has been modified This matches the behavior on trunk. Fixes an issue with not rendering the top toolbar when there was an empty default block and keeps the alt+f10 shortcut in line. --- .../block-editor/src/components/block-toolbar/index.js | 8 -------- packages/block-editor/src/components/block-tools/index.js | 7 ++++++- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 9eea40e89b3b4e..c5912c07682821 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -15,7 +15,6 @@ import { hasBlockSupport, isReusableBlock, isTemplatePart, - isUnmodifiedDefaultBlock, } from '@wordpress/blocks'; import { ToolbarGroup } from '@wordpress/components'; @@ -48,13 +47,11 @@ const BlockToolbar = ( { blockEditingMode, blockType, hasParents, - isEmptyDefaultBlock, isValid, isVisual, showParentSelector, } = useSelect( ( select ) => { const { - getBlock, getBlockName, getBlockMode, getBlockParents, @@ -79,9 +76,6 @@ const BlockToolbar = ( { getBlockType( getBlockName( selectedBlockClientId ) ), hasParents: parents.length, - isEmptyDefaultBlock: isUnmodifiedDefaultBlock( - getBlock( selectedBlockClientId ) || {} - ), isValid: selectedBlockClientIds.every( ( id ) => isBlockValid( id ) ), @@ -119,7 +113,6 @@ const BlockToolbar = ( { const hasAnyBlockControls = useHasAnyBlockControls(); if ( - isEmptyDefaultBlock || ! isToolbarEnabled || ( blockEditingMode !== 'default' && ! hasAnyBlockControls ) ) { @@ -140,7 +133,6 @@ const BlockToolbar = ( { const innerClasses = classnames( 'block-editor-block-toolbar', { 'is-synced': isSynced, } ); - return ( Date: Wed, 22 Nov 2023 15:38:47 -0600 Subject: [PATCH 10/51] Only use block popover on large screens --- packages/block-editor/src/components/block-tools/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 89ca887344a97a..4bfdf3ee161479 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -196,6 +196,7 @@ export default function BlockTools( { ) } { ! hasFixedToolbar && + isLargeViewport && ! showEmptyBlockSideInserter && hasSelectedBlock && ! isEmptyDefaultBlock && ( From 69ab86e09b093b515c143d4aa384282f692b39d8 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 22 Nov 2023 15:46:47 -0600 Subject: [PATCH 11/51] Remove unused showEmptyBlockSideInserter props --- .../src/components/block-tools/block-toolbar-breadcrumb.js | 5 ----- .../src/components/block-tools/block-toolbar-popover.js | 5 ----- 2 files changed, 10 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js b/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js index 0fe8fbb8ba48ba..9ed039a177d96b 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js @@ -19,7 +19,6 @@ import useSelectedBlockToolProps from './use-selected-block-tool-props'; export default function BlockToolbarBreadcrumb( { clientId, - showEmptyBlockSideInserter, __unstableContentRef, } ) { const { @@ -47,10 +46,6 @@ export default function BlockToolbarBreadcrumb( { clientId, } ); - if ( showEmptyBlockSideInserter ) { - return null; - } - if ( shouldShowBreadcrumb ) { return ( Date: Wed, 22 Nov 2023 16:26:42 -0600 Subject: [PATCH 12/51] Fix focus toolbar shortcut when breadcrumb and toolbar are both in DOM --- packages/block-editor/src/components/block-toolbar/index.js | 5 +++++ test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index c5912c07682821..ec5f7b89a751b7 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -47,6 +47,7 @@ const BlockToolbar = ( { blockEditingMode, blockType, hasParents, + isKeyboardFocusShortcutActive, isValid, isVisual, showParentSelector, @@ -57,6 +58,7 @@ const BlockToolbar = ( { getBlockParents, getSelectedBlockClientIds, isBlockValid, + isNavigationMode, getBlockRootClientId, getBlockEditingMode, } = select( blockEditorStore ); @@ -76,6 +78,8 @@ const BlockToolbar = ( { getBlockType( getBlockName( selectedBlockClientId ) ), hasParents: parents.length, + isKeyboardFocusShortcutActive: + isFixed || ( ! isFixed && ! isNavigationMode() ), isValid: selectedBlockClientIds.every( ( id ) => isBlockValid( id ) ), @@ -136,6 +140,7 @@ const BlockToolbar = ( { return ( { // Test: Focus the block toolbar from empty block await editor.insertBlock( { name: 'core/paragraph' } ); + // This fails if we don't wait for the block toolbar to show. + await expect( + toolbarUtils.blockToolbarParagraphButton + ).toBeVisible(); await toolbarUtils.moveToToolbarShortcut(); await expect( toolbarUtils.blockToolbarParagraphButton From 65eacfb53c5003511cedf485c56aa372b4e66f43 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 29 Nov 2023 09:30:28 -0600 Subject: [PATCH 13/51] Cleanup Block Popover comments --- .../src/components/block-tools/block-toolbar-popover.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index 0512269bf7f9da..0b97b3307d31f8 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -26,7 +26,6 @@ export default function BlockToolbarPopover( { const { shouldShowContextualToolbar } = useShouldContextualToolbarShow(); - // There shouldn't be an idea of focus on mount. It's just "Does the shortcut work or not". If there are block tools it can be focused. If the block tools have been accessed, the same tabindex will be persisted until it is remounted via a block change. return ( Date: Wed, 29 Nov 2023 10:30:08 -0600 Subject: [PATCH 14/51] Deprecate focusOnMount --- .../src/components/navigable-toolbar/index.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/navigable-toolbar/index.js b/packages/block-editor/src/components/navigable-toolbar/index.js index 7a56ad1835b93d..b18c1050c8f046 100644 --- a/packages/block-editor/src/components/navigable-toolbar/index.js +++ b/packages/block-editor/src/components/navigable-toolbar/index.js @@ -98,7 +98,7 @@ function useToolbarFocus( { shouldUseKeyboardFocusShortcut, focusEditorOnEscape, } ) { - // Make sure we don't use modified versions of this prop. + // Deprecated in 6.5.0 const [ initialFocusOnMount ] = useState( focusOnMount ); const { stopTyping } = useDispatch( blockEditorStore ); @@ -116,7 +116,7 @@ function useToolbarFocus( { // Focus on toolbar when pressing alt+F10 when the toolbar is visible. useShortcut( 'core/block-editor/focus-toolbar', focusToolbarViaShortcut ); - // Unused in codebase. Do we need to keep it for backwards compatability? + // Deprecated in 6.5.0 useEffect( () => { if ( initialFocusOnMount ) { focusToolbar(); @@ -163,6 +163,14 @@ export default function NavigableToolbar( { } ) { const toolbarRef = useRef(); const isAccessibleToolbar = useIsAccessibleToolbar( toolbarRef ); + + if ( focusOnMount ) { + deprecated( 'The focusOnMount prop', { + since: '6.5', + version: '6.6', + } ); + } + useToolbarFocus( { toolbarRef, focusOnMount, From 4198787b4b7c871a2db65042b0289e3ed7c54b40 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 29 Nov 2023 10:48:58 -0600 Subject: [PATCH 15/51] Remove shouldUseKeyboardFocusShortcut prop from use in BlockToolbar --- .../src/components/block-toolbar/index.js | 6 +- .../block-tools/block-toolbar-breadcrumb.js | 58 +++++-------------- .../src/components/block-tools/index.js | 28 +++++---- 3 files changed, 35 insertions(+), 57 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index ec5f7b89a751b7..1ff5a7cf07f963 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -47,7 +47,6 @@ const BlockToolbar = ( { blockEditingMode, blockType, hasParents, - isKeyboardFocusShortcutActive, isValid, isVisual, showParentSelector, @@ -58,7 +57,6 @@ const BlockToolbar = ( { getBlockParents, getSelectedBlockClientIds, isBlockValid, - isNavigationMode, getBlockRootClientId, getBlockEditingMode, } = select( blockEditorStore ); @@ -78,8 +76,6 @@ const BlockToolbar = ( { getBlockType( getBlockName( selectedBlockClientId ) ), hasParents: parents.length, - isKeyboardFocusShortcutActive: - isFixed || ( ! isFixed && ! isNavigationMode() ), isValid: selectedBlockClientIds.every( ( id ) => isBlockValid( id ) ), @@ -137,10 +133,10 @@ const BlockToolbar = ( { const innerClasses = classnames( 'block-editor-block-toolbar', { 'is-synced': isSynced, } ); + return ( { - const { hasMultiSelection, __unstableGetEditorMode } = - select( blockEditorStore ); - - const editorMode = __unstableGetEditorMode(); - - return { - shouldShowBreadcrumb: - ! hasMultiSelection() && - ( editorMode === 'navigation' || editorMode === 'zoom-out' ), - }; - }, [] ); - const popoverProps = useBlockToolbarPopoverProps( { contentElement: __unstableContentRef?.current, clientId, } ); - if ( shouldShowBreadcrumb ) { - return ( - - - - ); - } - - return null; + return ( + + + + ); } diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 4bfdf3ee161479..51ffb632b37b95 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -29,6 +29,7 @@ function selector( select ) { getFirstMultiSelectedBlockClientId, getBlock, getSettings, + hasMultiSelection, __unstableGetEditorMode, isTyping, } = select( blockEditorStore ); @@ -37,7 +38,7 @@ function selector( select ) { getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId(); const { name = '', attributes = {} } = getBlock( clientId ) || {}; - + const editorMode = __unstableGetEditorMode(); return { clientId, hasFixedToolbar: getSettings().hasFixedToolbar, @@ -46,12 +47,15 @@ function selector( select ) { getBlock( clientId ) || {} ), isTyping: isTyping(), - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + isZoomOutMode: editorMode === 'zoom-out', showEmptyBlockSideInserter: clientId && ! isTyping() && - __unstableGetEditorMode() === 'edit' && + editorMode === 'edit' && isUnmodifiedDefaultBlock( { name, attributes } ), + shouldShowBreadcrumb: + ! hasMultiSelection() && + ( editorMode === 'navigation' || editorMode === 'zoom-out' ), }; } @@ -78,6 +82,7 @@ export default function BlockTools( { isTyping, isZoomOutMode, showEmptyBlockSideInserter, + shouldShowBreadcrumb, } = useSelect( selector, [] ); const isMatch = useShortcutEventMatch(); const { getSelectedBlockClientIds, getBlockRootClientId } = @@ -199,19 +204,22 @@ export default function BlockTools( { isLargeViewport && ! showEmptyBlockSideInserter && hasSelectedBlock && - ! isEmptyDefaultBlock && ( + ! isEmptyDefaultBlock && + ! shouldShowBreadcrumb && ( ) } - { ! showEmptyBlockSideInserter && hasSelectedBlock && ( - - ) } + { ! showEmptyBlockSideInserter && + hasSelectedBlock && + shouldShowBreadcrumb && ( + + ) } { /* Used for the inline rich text toolbar. */ } { ! isTopToolbar && ( From 109b1a0ce4999420d4675babd6f1368a050737a7 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 29 Nov 2023 12:33:11 -0600 Subject: [PATCH 16/51] Add __experimentalBlockToolbarDisplay prop to BlockTools and implement in post-edit --- packages/block-editor/README.md | 1 + .../src/components/block-tools/index.js | 41 +++++++------------ 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 2d6a5627a52a44..930a5871a2bae8 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -293,6 +293,7 @@ _Parameters_ - _$0_ `Object`: Props. - _$0.children_ `Object`: The block content and style container. - _$0.\_\_unstableContentRef_ `Object`: Ref holding the content scroll container. +- _$0.\_\_experimentalBlockToolbarDisplay_ `string`: The display mode for the block toolbar. ### BlockVerticalAlignmentControl diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 51ffb632b37b95..dab5a5019d9f63 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { useViewportMatch } from '@wordpress/compose'; import { Popover } from '@wordpress/components'; import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts'; import { useRef } from '@wordpress/element'; @@ -28,7 +27,6 @@ function selector( select ) { getSelectedBlockClientId, getFirstMultiSelectedBlockClientId, getBlock, - getSettings, hasMultiSelection, __unstableGetEditorMode, isTyping, @@ -41,7 +39,6 @@ function selector( select ) { const editorMode = __unstableGetEditorMode(); return { clientId, - hasFixedToolbar: getSettings().hasFixedToolbar, hasSelectedBlock: clientId && name, isEmptyDefaultBlock: isUnmodifiedDefaultBlock( getBlock( clientId ) || {} @@ -64,19 +61,19 @@ function selector( select ) { * insertion point and a slot for the inline rich text toolbar). Must be wrapped * around the block content and editor styles wrapper or iframe. * - * @param {Object} $0 Props. - * @param {Object} $0.children The block content and style container. - * @param {Object} $0.__unstableContentRef Ref holding the content scroll container. + * @param {Object} $0 Props. + * @param {Object} $0.children The block content and style container. + * @param {Object} $0.__unstableContentRef Ref holding the content scroll container. + * @param {string} $0.__experimentalBlockToolbarDisplay The display mode for the block toolbar. */ export default function BlockTools( { children, __unstableContentRef, + __experimentalBlockToolbarDisplay = 'popover', ...props } ) { - const isLargeViewport = useViewportMatch( 'medium' ); const { clientId, - hasFixedToolbar, hasSelectedBlock, isEmptyDefaultBlock, isTyping, @@ -172,12 +169,6 @@ export default function BlockTools( { const blockToolbarRef = usePopoverScroll( __unstableContentRef ); const blockToolbarAfterRef = usePopoverScroll( __unstableContentRef ); - // Conditions for fixed toolbar - // 1. Not zoom out mode - // 2. It's a large viewport. If it's a smaller viewport, let the floating toolbar handle it as it already has styles attached to make it render that way. - // 3. Fixed toolbar is enabled - const isTopToolbar = ! isZoomOutMode && hasFixedToolbar && isLargeViewport; - return ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions
@@ -187,10 +178,8 @@ export default function BlockTools( { __unstableContentRef={ __unstableContentRef } /> ) } - { /* If there is no slot available, such as in the standalone block editor, render within the editor */ } - - { ! isLargeViewport && ( // Small viewports always get a fixed toolbar - + { __experimentalBlockToolbarDisplay === 'sticky' && ( + ) } { showEmptyBlockSideInserter && ( @@ -200,8 +189,7 @@ export default function BlockTools( { /> ) } - { ! hasFixedToolbar && - isLargeViewport && + { __experimentalBlockToolbarDisplay === 'popover' && ! showEmptyBlockSideInserter && hasSelectedBlock && ! isEmptyDefaultBlock && @@ -222,12 +210,13 @@ export default function BlockTools( { ) } { /* Used for the inline rich text toolbar. */ } - { ! isTopToolbar && ( - - ) } + { ! isZoomOutMode && + __experimentalBlockToolbarDisplay === 'popover' && ( + + ) } { children } { /* Used for inline rich text popovers. */ } Date: Wed, 29 Nov 2023 12:34:45 -0600 Subject: [PATCH 17/51] Temporarily add isFixed prop back to sticky toolbar --- packages/block-editor/src/components/block-tools/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index dab5a5019d9f63..3961befa4c7536 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -179,7 +179,7 @@ export default function BlockTools( { /> ) } { __experimentalBlockToolbarDisplay === 'sticky' && ( - + ) } { showEmptyBlockSideInserter && ( From 9399a327174d90b6efc5468ed931941f1fe5ba8d Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 29 Nov 2023 12:49:41 -0600 Subject: [PATCH 18/51] Use __experimentalBlockToolbarDisplay in Edit Widgets BlockTools --- .../index.js | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js b/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js index 12a70e2e4da279..2efb5fb8808904 100644 --- a/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js +++ b/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js @@ -8,6 +8,7 @@ import { WritingFlow, __unstableEditorStyles as EditorStyles, } from '@wordpress/block-editor'; +import { useViewportMatch } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; import { useMemo } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -21,14 +22,26 @@ import KeyboardShortcuts from '../keyboard-shortcuts'; export default function WidgetAreasBlockEditorContent( { blockEditorSettings, } ) { - const hasThemeStyles = useSelect( - ( select ) => - !! select( preferencesStore ).get( + const { hasTopToolbar, hasThemeStyles } = useSelect( ( select ) => { + return { + hasTopToolbar: !! select( preferencesStore ).get( + 'core/edit-widgets', + 'fixedToolbar' + ), + hasThemeStyles: !! select( preferencesStore ).get( 'core/edit-widgets', 'themeStyles' ), - [] - ); + }; + }, [] ); + const isLargeViewport = useViewportMatch( 'medium' ); + let blockToolbarDisplay = 'popover'; + + if ( ! isLargeViewport ) { + blockToolbarDisplay = 'sticky'; + } else if ( hasTopToolbar ) { + blockToolbarDisplay = 'none'; + } const styles = useMemo( () => { return hasThemeStyles ? blockEditorSettings.styles : []; @@ -37,7 +50,9 @@ export default function WidgetAreasBlockEditorContent( { return (
- + Date: Wed, 29 Nov 2023 13:08:33 -0600 Subject: [PATCH 19/51] Fix incorrect if statement for block tools and add comment --- packages/block-editor/src/components/block-tools/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 3961befa4c7536..251e2f36f67faa 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -209,9 +209,10 @@ export default function BlockTools( { /> ) } - { /* Used for the inline rich text toolbar. */ } + { /* Used for the inline rich text toolbar. Until this toolbar is combined into BlockToolbar, someone implementing their own BlockToolbar will also need to use this to see the image caption toolbar. */ } { ! isZoomOutMode && - __experimentalBlockToolbarDisplay === 'popover' && ( + ( __experimentalBlockToolbarDisplay === 'popover' || + __experimentalBlockToolbarDisplay === 'sticky' ) && ( Date: Wed, 29 Nov 2023 13:09:25 -0600 Subject: [PATCH 20/51] Use __experimentalBlockToolbarDisplay for widgets customizer --- .../src/components/header/index.js | 25 +++---------------- .../components/sidebar-block-editor/index.js | 16 ++++++++++-- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/packages/customize-widgets/src/components/header/index.js b/packages/customize-widgets/src/components/header/index.js index 5bd746715de998..5bd0b2c2f4d471 100644 --- a/packages/customize-widgets/src/components/header/index.js +++ b/packages/customize-widgets/src/components/header/index.js @@ -6,10 +6,9 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { Popover, ToolbarButton } from '@wordpress/components'; -import { useViewportMatch } from '@wordpress/compose'; -import { BlockToolbar, NavigableToolbar } from '@wordpress/block-editor'; -import { createPortal, useEffect, useRef, useState } from '@wordpress/element'; +import { ToolbarButton } from '@wordpress/components'; +import { NavigableToolbar } from '@wordpress/block-editor'; +import { createPortal, useEffect, useState } from '@wordpress/element'; import { displayShortcut, isAppleOS } from '@wordpress/keycodes'; import { __, _x, isRTL } from '@wordpress/i18n'; import { plus, undo as undoIcon, redo as redoIcon } from '@wordpress/icons'; @@ -27,8 +26,6 @@ function Header( { setIsInserterOpened, isFixedToolbarActive, } ) { - const isLargeViewport = useViewportMatch( 'medium' ); - const blockToolbarRef = useRef(); const [ [ hasUndo, hasRedo ], setUndoRedo ] = useState( [ sidebar.hasUndo(), sidebar.hasRedo(), @@ -101,22 +98,6 @@ function Header( { , inserter.contentContainer[ 0 ] ) } - - { isFixedToolbarActive && isLargeViewport && ( - <> -
- -
- - - ) } ); } diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/index.js b/packages/customize-widgets/src/components/sidebar-block-editor/index.js index ccb6fca871429e..2fd363318d383a 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -1,6 +1,7 @@ /** * WordPress dependencies */ +import { useViewportMatch } from '@wordpress/compose'; import { store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; import { useMemo, createPortal } from '@wordpress/element'; @@ -89,6 +90,9 @@ export default function SidebarBlockEditor( { setIsInserterOpened, ] ); + // This should be a small viewport, but the display of the toolbar is tied to the CSS, so it's not visible at small screens. Once the CSS tying the toolbar display to vieweport size is removed, we can change this to be a small viewport check. + const isLargeViewport = useViewportMatch( 'medium' ); + if ( isWelcomeGuideActive ) { return ; } @@ -109,10 +113,18 @@ export default function SidebarBlockEditor( { inserter={ inserter } isInserterOpened={ isInserterOpened } setIsInserterOpened={ setIsInserterOpened } - isFixedToolbarActive={ isFixedToolbarActive } + isFixedToolbarActive={ + isFixedToolbarActive || ! isLargeViewport + } /> - + Date: Wed, 29 Nov 2023 16:53:04 -0600 Subject: [PATCH 21/51] Remove isFixed from BlockToolbar component Huge change. I'm sorry. Completely reworked the CSS to designate a fixed toolbar as the baseline with the popover styles as overrides. Moved top toolbar specific styles into the headers of the respective areas rather than bundled with block toolbar. --- .../src/components/block-toolbar/index.js | 7 +- .../src/components/block-toolbar/style.scss | 99 +++++--- .../src/components/block-tools/index.js | 2 +- .../src/components/block-tools/style.scss | 222 ++++-------------- .../sidebar-block-editor/style.scss | 20 -- .../edit-post/src/components/header/index.js | 6 +- .../src/components/header/style.scss | 39 ++- .../src/components/block-editor/style.scss | 11 - .../src/components/header-edit-mode/index.js | 1 - .../components/header-edit-mode/style.scss | 28 ++- .../src/components/header/index.js | 1 - .../src/components/header/style.scss | 36 ++- 12 files changed, 210 insertions(+), 262 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 1ff5a7cf07f963..9e75a076d4191b 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -36,11 +36,7 @@ import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls'; -const BlockToolbar = ( { - hideDragHandle, - isFixed, // TODO: Remove isFixed. That is a temporary prop to support the old fixed toolbar. All toolbars will be "fixed"/don't care about this distinction. - variant, -} ) => { +const BlockToolbar = ( { hideDragHandle, variant } ) => { const { blockClientId, blockClientIds, @@ -127,7 +123,6 @@ const BlockToolbar = ( { // Shifts the toolbar to make room for the parent block selector. const classes = classnames( 'block-editor-block-contextual-toolbar', { 'has-parent': hasParents && showParentSelector, - 'is-fixed': isFixed, } ); const innerClasses = classnames( 'block-editor-block-toolbar', { diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index 3f8a7057aef84f..eb7ebaac2cd7b3 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -56,57 +56,86 @@ } } -.block-editor-block-contextual-toolbar.is-fixed { +.block-editor-block-contextual-toolbar { position: sticky; top: 0; z-index: z-index(".block-editor-block-popover"); display: block; width: 100%; -} -// on desktop browsers the fixed toolbar has tweaked borders -@include break-medium() { - .block-editor-block-contextual-toolbar.is-fixed { - .block-editor-block-toolbar { - .components-toolbar-group, - .components-toolbar { - border-right: none; - - &::after { - content: ""; - width: $border-width; - margin-top: $grid-unit + $grid-unit-05; - margin-bottom: $grid-unit + $grid-unit-05; - background-color: $gray-300; - margin-left: $grid-unit; - } - - & .components-toolbar-group.components-toolbar-group { - &::after { - display: none; - } - } - } + // Block UI appearance. + background-color: $white; + flex-shrink: 3; + + // Raise the specificity. + &.components-accessible-toolbar { + border-bottom: $border-width solid $gray-200; + border-radius: 0; + } - > :last-child, - > :last-child .components-toolbar-group, - > :last-child .components-toolbar { - &::after { - display: none; - } + .block-editor-block-toolbar { + overflow: auto; + overflow-y: hidden; + + > :last-child, + > :last-child .components-toolbar-group, + > :last-child .components-toolbar { + &::after { + display: none; } } } -} -.block-editor-block-contextual-toolbar.has-parent:not(.is-fixed) { - margin-left: calc(#{$grid-unit-60} + #{$grid-unit-10}); + .block-editor-block-toolbar .components-toolbar-group, + .block-editor-block-toolbar .components-toolbar { + border-right-color: $gray-200; + } + + & > .block-editor-block-toolbar { + flex-grow: initial; + width: initial; + } .show-icon-labels & { - margin-left: 0; + .block-editor-block-parent-selector .block-editor-block-parent-selector__button::after { + left: 0; + } + + .block-editor-block-toolbar__block-controls .block-editor-block-mover { + border-left: none; + &::before { + content: ""; + width: $border-width; + margin-top: $grid-unit + $grid-unit-05; + margin-bottom: $grid-unit + $grid-unit-05; + background-color: $gray-300; + position: relative; + } + } + } + + .block-editor-block-parent-selector { + + .block-editor-block-parent-selector__button { + position: relative; + top: -1px; + border: 0; + padding-right: 6px; + padding-left: 6px; + + &::after { + content: "\00B7"; + font-size: 16px; + line-height: $grid-unit-40 + $grid-unit-10; + position: absolute; + left: $grid-unit-40 + $grid-unit-15 + 2px; + bottom: $grid-unit-05; + } + } } } + // Block controls. .block-editor-block-toolbar__block-controls { // Switcher. diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 251e2f36f67faa..ba96595fe2a523 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -179,7 +179,7 @@ export default function BlockTools( { /> ) } { __experimentalBlockToolbarDisplay === 'sticky' && ( - + ) } { showEmptyBlockSideInserter && ( diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 07f22bb4946ea2..4632ce01f3c2aa 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -85,178 +85,6 @@ } } -/** - * Block Toolbar when contextual. - */ - -.block-editor-block-contextual-toolbar { - // Block UI appearance. - display: inline-flex; - border: $border-width solid $gray-900; - border-radius: $radius-block-ui; - background-color: $white; - - .block-editor-block-toolbar .components-toolbar-group, - .block-editor-block-toolbar .components-toolbar { - border-right-color: $gray-900; - } - - &.is-fixed { - overflow: hidden; - - .block-editor-block-toolbar { - overflow: auto; - overflow-y: hidden; - } - - border-bottom: $border-width solid $gray-200; - border-radius: 0; - - .block-editor-block-toolbar .components-toolbar-group, - .block-editor-block-toolbar .components-toolbar { - border-right-color: $gray-200; - } - } - - @include break-medium() { - &.is-fixed { - & > .block-editor-block-toolbar { - flex-grow: initial; - width: initial; - - // Add a border as separator in the block toolbar. - &::before { - content: ""; - width: $border-width; - height: 3 * $grid-unit; - margin-top: $grid-unit + $grid-unit-05; - margin-right: 0; - background-color: $gray-300; - position: relative; - left: math.div(-$grid-unit-05, 2); - top: -1px; - } - } - - & > .block-editor-block-toolbar__group-collapse-fixed-toolbar { - border: none; - - .show-icon-labels & { - .components-button.has-icon { - // Hide the button icons when labels are set to display... - svg { - display: none; - } - // ... and display labels. - &::after { - content: attr(aria-label); - font-size: $helptext-font-size; - } - } - } - - // Add a border as separator in the block toolbar. - &::before { - content: ""; - width: $border-width; - height: 3 * $grid-unit; - margin-top: $grid-unit + $grid-unit-05; - margin-right: $grid-unit-10; - background-color: $gray-300; - position: relative; - left: 0; - top: -1px; - } - } - - & > .block-editor-block-toolbar__group-expand-fixed-toolbar { - border: none; - - .show-icon-labels & { - width: $grid-unit-80 * 4; - .components-button.has-icon { - // Hide the button icons when labels are set to display... - svg { - display: none; - } - // ... and display labels. - &::after { - content: attr(aria-label); - font-size: $helptext-font-size; - } - } - } - - // Add a border as separator in the block toolbar. - &::before { - content: ""; - width: $border-width; - margin-top: $grid-unit + $grid-unit-05; - margin-bottom: $grid-unit + $grid-unit-05; - background-color: $gray-300; - position: relative; - left: -8px; - height: 3 * $grid-unit; - top: -1px; - } - } - - .show-icon-labels & { - .block-editor-block-parent-selector .block-editor-block-parent-selector__button::after { - left: 0; - } - - .block-editor-block-toolbar__block-controls .block-editor-block-mover { - border-left: none; - &::before { - content: ""; - width: $border-width; - margin-top: $grid-unit + $grid-unit-05; - margin-bottom: $grid-unit + $grid-unit-05; - background-color: $gray-300; - position: relative; - } - } - } - } - - &.is-fixed .block-editor-block-parent-selector { - - .block-editor-block-parent-selector__button { - position: relative; - top: -1px; - border: 0; - padding-right: 6px; - padding-left: 6px; - - &::after { - content: "\00B7"; - font-size: 16px; - line-height: $grid-unit-40 + $grid-unit-10; - position: absolute; - left: $grid-unit-40 + $grid-unit-15 + 2px; - bottom: $grid-unit-05; - } - } - } - - &:not(.is-fixed) .block-editor-block-parent-selector { - position: absolute; - top: -$border-width; - left: calc(-#{$grid-unit-60} - #{$grid-unit-10} - #{$border-width}); - - .show-icon-labels & { - position: relative; - left: auto; - top: auto; - margin-top: -$border-width; - margin-left: -$border-width; - margin-bottom: -$border-width; - } - } - } -} - /** * Block Label for Navigation/Selection Mode */ @@ -349,6 +177,7 @@ } .components-popover.block-editor-block-list__block-popover { + // Position the block toolbar. .block-editor-block-list__block-selection-button, .block-editor-block-contextual-toolbar { @@ -357,6 +186,30 @@ margin-bottom: $grid-unit-15; } + .block-editor-block-contextual-toolbar { + border: $border-width solid $gray-900; + border-radius: $radius-block-ui; + overflow: visible; // allow the parent selector to be visible + position: static; + width: auto; + + &.has-parent { + margin-left: calc(#{$grid-unit-60} + #{$grid-unit-10}); + .show-icon-labels & { + margin-left: 0; + } + } + } + + .block-editor-block-toolbar { + overflow: visible; + } + + .block-editor-block-toolbar .components-toolbar-group, + .block-editor-block-toolbar .components-toolbar { + border-right-color: $gray-900; + } + // Hide the block toolbar if the insertion point is shown. &.is-insertion-point-visible { visibility: hidden; @@ -368,6 +221,31 @@ // It's essential to hide the toolbar/popover so that `dragEnter` events can pass through them to the underlying elements. animation: hide-during-dragging 1ms linear forwards; } + + .block-editor-block-parent-selector { + position: absolute; + left: calc(-#{$grid-unit-60} - #{$grid-unit-10} - #{$border-width}); + + .block-editor-block-parent-selector__button { + position: relative; + border: 1px solid $gray-900; + padding-right: 6px; + padding-left: 6px; + + &::after { + content: ""; + } + } + + .show-icon-labels & { + position: relative; + left: auto; + top: auto; + margin-top: -$border-width; + margin-left: -$border-width; + margin-bottom: -$border-width; + } + } } .is-dragging-components-draggable .components-tooltip { diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/style.scss b/packages/customize-widgets/src/components/sidebar-block-editor/style.scss index a1b99447155eb2..1aa62ed32e847c 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/style.scss +++ b/packages/customize-widgets/src/components/sidebar-block-editor/style.scss @@ -1,23 +1,3 @@ -.block-editor-block-contextual-toolbar.is-fixed { - // The top position used for the 'sticky' positioning. - top: 0; - - // Offset the customizer's sidebar padding. - margin-left: -$grid-unit-15; - margin-right: -$grid-unit-15; - // added important to override the inline style coming from - // the block-editor/block-contextual-toolbar component. - width: calc(100% + #{ $grid-unit-30 }) !important; - - & > .block-editor-block-toolbar__group-collapse-fixed-toolbar { - display: none; - } - - // Scroll sideways. - overflow-y: auto; - z-index: z-index(".customize-widgets__block-toolbar"); -} - .customize-control-sidebar_block_editor .block-editor-block-list__block-popover { // FloatingUI library used in Popover component forces us to have an "absolute" inline style. // We need to override this in the customizer. diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js index d7c298535924ef..73fba82eb8231e 100644 --- a/packages/edit-post/src/components/header/index.js +++ b/packages/edit-post/src/components/header/index.js @@ -127,11 +127,7 @@ function Header( { } ) } > - +
diff --git a/packages/edit-site/src/components/header-edit-mode/style.scss b/packages/edit-site/src/components/header-edit-mode/style.scss index 0fe335c5292ba2..0cfe452805ac37 100644 --- a/packages/edit-site/src/components/header-edit-mode/style.scss +++ b/packages/edit-site/src/components/header-edit-mode/style.scss @@ -49,9 +49,6 @@ $header-toolbar-min-width: 335px; min-width: 0; } - .block-editor-block-contextual-toolbar.is-fixed { - border: none; - } } .edit-site-header-edit-mode__toolbar { @@ -197,6 +194,31 @@ $header-toolbar-min-width: 335px; .selected-block-tools-wrapper { overflow-x: scroll; + .block-editor-block-contextual-toolbar { + border-bottom: 0; + } + + // Modified group borders + .components-toolbar-group, + .components-toolbar { + border-right: none; + + &::after { + content: ""; + width: $border-width; + margin-top: $grid-unit + $grid-unit-05; + margin-bottom: $grid-unit + $grid-unit-05; + background-color: $gray-300; + margin-left: $grid-unit; + } + + & .components-toolbar-group.components-toolbar-group { + &::after { + display: none; + } + } + } + &.is-collapsed { display: none; } diff --git a/packages/edit-widgets/src/components/header/index.js b/packages/edit-widgets/src/components/header/index.js index ea28ddbb28419c..10ea61535a6e98 100644 --- a/packages/edit-widgets/src/components/header/index.js +++ b/packages/edit-widgets/src/components/header/index.js @@ -54,7 +54,6 @@ function Header( { setListViewToggleElement } ) { <>
diff --git a/packages/edit-widgets/src/components/header/style.scss b/packages/edit-widgets/src/components/header/style.scss index e279b0f79b4585..5a45e7033872f8 100644 --- a/packages/edit-widgets/src/components/header/style.scss +++ b/packages/edit-widgets/src/components/header/style.scss @@ -12,10 +12,40 @@ .selected-block-tools-wrapper { overflow-x: hidden; - } - .block-editor-block-contextual-toolbar.is-fixed { - border: none; + .block-editor-block-contextual-toolbar { + border-bottom: 0; + } + + &::after { + content: ""; + width: $border-width; + margin-top: $grid-unit + $grid-unit-05; + margin-bottom: $grid-unit + $grid-unit-05; + background-color: $gray-300; + margin-left: $grid-unit; + } + + // Modified group borders + .components-toolbar-group, + .components-toolbar { + border-right: none; + + &::after { + content: ""; + width: $border-width; + margin-top: $grid-unit + $grid-unit-05; + margin-bottom: $grid-unit + $grid-unit-05; + background-color: $gray-300; + margin-left: $grid-unit; + } + + & .components-toolbar-group.components-toolbar-group { + &::after { + display: none; + } + } + } } } From 9fb88a651a0a262c81af32ac5f03559649262d94 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 30 Nov 2023 09:35:21 -0600 Subject: [PATCH 22/51] Update is-typing e2e tests - Switch from visibility/hidden check to opacity check. Playwright considers hidden as width/height of 0 or visibility: hidden/display:none. The popover is hidden with opacity and z-index to move it to the back, so these aren't considered hidden to plawyright. - Move to clicks on query block dropdown test. The Enter keypresses were happening before the screen was updated, so it was flakey. --- .../specs/editor/various/is-typing.spec.js | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/test/e2e/specs/editor/various/is-typing.spec.js b/test/e2e/specs/editor/various/is-typing.spec.js index 0cd5e0d6f64953..583f1ec97c725e 100644 --- a/test/e2e/specs/editor/various/is-typing.spec.js +++ b/test/e2e/specs/editor/various/is-typing.spec.js @@ -14,24 +14,27 @@ test.describe( 'isTyping', () => { // Insert paragraph await page.keyboard.type( 'Type' ); - const blockToolbar = page.locator( - 'role=toolbar[name="Block tools"i]' + const blockToolbarPopover = page.locator( + '[data-wp-component="Popover"]', + { + has: page.locator( 'role=toolbar[name="Block tools"i]' ), + } ); - // Toolbar should not be showing - await expect( blockToolbar ).toBeHidden(); + // Toolbar Popover should not be showing + await expect( blockToolbarPopover ).toHaveCSS( 'opacity', '0' ); // Moving the mouse shows the toolbar. await editor.showBlockToolbar(); - // Toolbar is visible. - await expect( blockToolbar ).toBeVisible(); + // Toolbar Popover is visible. + await expect( blockToolbarPopover ).toHaveCSS( 'opacity', '1' ); // Typing again hides the toolbar await page.keyboard.type( ' and continue' ); - // Toolbar is hidden again - await expect( blockToolbar ).toBeHidden(); + // Toolbar Popover is hidden again + await expect( blockToolbarPopover ).toHaveCSS( 'opacity', '0' ); } ); test( 'should not close the dropdown when typing in it', async ( { @@ -41,17 +44,22 @@ test.describe( 'isTyping', () => { // Add a block with a dropdown in the toolbar that contains an input. await editor.insertBlock( { name: 'core/query' } ); - // Tab to Start Blank Button - await page.keyboard.press( 'Tab' ); - // Select the Start Blank Button - await page.keyboard.press( 'Enter' ); - // Select the First variation - await page.keyboard.press( 'Enter' ); + await editor.canvas + .getByRole( 'document', { name: 'Block: Query Loop' } ) + .getByRole( 'button', { name: 'Start blank' } ) + .click(); + + await editor.canvas + .getByRole( 'button', { name: 'Title & Date' } ) + .click(); + // Moving the mouse shows the toolbar. await editor.showBlockToolbar(); // Open the dropdown. - await page.getByRole( 'button', { name: 'Display settings' } ).click(); - + const displaySettings = page.getByRole( 'button', { + name: 'Display settings', + } ); + await displaySettings.click(); const itemsPerPageInput = page.getByLabel( 'Items per Page' ); // Make sure we're where we think we are await expect( itemsPerPageInput ).toBeFocused(); From ae4c062e68fd68e390bbcf94e5d91d2f687f9a9b Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 30 Nov 2023 14:23:13 -0600 Subject: [PATCH 23/51] Update storybook examples to use __experimentalBlockToolbarDisplay --- storybook/stories/playground/box/index.js | 5 +---- storybook/stories/playground/with-undo-redo/index.js | 5 +---- storybook/stories/playground/with-undo-redo/style.css | 6 +++++- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/storybook/stories/playground/box/index.js b/storybook/stories/playground/box/index.js index 444b7810e5e89e..e578dfd428904e 100644 --- a/storybook/stories/playground/box/index.js +++ b/storybook/stories/playground/box/index.js @@ -32,11 +32,8 @@ export default function EditorBox() { value={ blocks } onInput={ updateBlocks } onChange={ updateBlocks } - settings={ { - hasFixedToolbar: true, - } } > - +
diff --git a/storybook/stories/playground/with-undo-redo/index.js b/storybook/stories/playground/with-undo-redo/index.js index a51d8624282a6d..0bf791355f7fa8 100644 --- a/storybook/stories/playground/with-undo-redo/index.js +++ b/storybook/stories/playground/with-undo-redo/index.js @@ -41,9 +41,6 @@ export default function EditorWithUndoRedo() { onChange={ ( blocks, { selection } ) => setValue( { blocks, selection }, false ) } - settings={ { - hasFixedToolbar: true, - } } >
diff --git a/storybook/stories/playground/with-undo-redo/style.css b/storybook/stories/playground/with-undo-redo/style.css index a3f0bd5d23debf..6ed082a1de7196 100644 --- a/storybook/stories/playground/with-undo-redo/style.css +++ b/storybook/stories/playground/with-undo-redo/style.css @@ -6,5 +6,9 @@ display: flex; align-items: center; border-bottom: 1px solid #ddd; - height: 48px; + height: 46px; } + +.editor-with-undo-redo__toolbar .components-accessible-toolbar.block-editor-block-contextual-toolbar { + border-bottom: none; +} \ No newline at end of file From 4ac80eed5e3b86f47ddfbfceacc05cb409895053 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 30 Nov 2023 16:56:29 -0600 Subject: [PATCH 24/51] Hide block toolbar popover when typing --- .../block-tools/block-toolbar-popover.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index 0b97b3307d31f8..365212877e33e3 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -3,19 +3,29 @@ */ import classnames from 'classnames'; +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + /** * Internal dependencies */ +import { store as blockEditorStore } from '../../store'; import BlockToolbar from '../block-toolbar'; import BlockPopover from '../block-popover'; import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; import useSelectedBlockToolProps from './use-selected-block-tool-props'; -import { useShouldContextualToolbarShow } from '../../utils/use-should-contextual-toolbar-show'; export default function BlockToolbarPopover( { clientId, __unstableContentRef, } ) { + const isTyping = useSelect( + ( select ) => select( blockEditorStore ).isTyping(), + [] + ); + const { capturingClientId, isInsertionPointVisible, lastClientId } = useSelectedBlockToolProps( clientId ); @@ -24,15 +34,13 @@ export default function BlockToolbarPopover( { clientId, } ); - const { shouldShowContextualToolbar } = useShouldContextualToolbarShow(); - return ( Date: Thu, 30 Nov 2023 16:57:22 -0600 Subject: [PATCH 25/51] Use sticky toolbar on customize widget until small screen breakpoint --- .../customize-widgets/src/components/header/style.scss | 2 +- .../src/components/sidebar-block-editor/index.js | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/customize-widgets/src/components/header/style.scss b/packages/customize-widgets/src/components/header/style.scss index d9d4a487e647c1..27460a82e0ad10 100644 --- a/packages/customize-widgets/src/components/header/style.scss +++ b/packages/customize-widgets/src/components/header/style.scss @@ -1,5 +1,5 @@ .customize-widgets-header { - @include break-medium() { + @include break-small() { // Make space for the floating toolbar. margin-bottom: $grid-unit-20 + $default-block-margin; } diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/index.js b/packages/customize-widgets/src/components/sidebar-block-editor/index.js index 2fd363318d383a..bd66fd3b7d2160 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -90,8 +90,7 @@ export default function SidebarBlockEditor( { setIsInserterOpened, ] ); - // This should be a small viewport, but the display of the toolbar is tied to the CSS, so it's not visible at small screens. Once the CSS tying the toolbar display to vieweport size is removed, we can change this to be a small viewport check. - const isLargeViewport = useViewportMatch( 'medium' ); + const isMediumViewport = useViewportMatch( 'small' ); if ( isWelcomeGuideActive ) { return ; @@ -114,13 +113,13 @@ export default function SidebarBlockEditor( { isInserterOpened={ isInserterOpened } setIsInserterOpened={ setIsInserterOpened } isFixedToolbarActive={ - isFixedToolbarActive || ! isLargeViewport + isFixedToolbarActive || ! isMediumViewport } /> Date: Fri, 1 Dec 2023 11:41:01 -0600 Subject: [PATCH 26/51] Edit Post: hasFixedToolbar = do not render the within Note: Edit Site and Widgets are likely broken. This is a POC to show how we could implement the idea of hasFixedToolbar = do not render within and still meet all the layout and design requirements of WordPress Post Editor. --- packages/block-editor/README.md | 1 - .../src/components/block-tools/index.js | 31 ++++++++----------- .../edit-post/src/components/layout/index.js | 18 +++++------ .../src/components/layout/style.scss | 6 ++++ packages/edit-post/src/editor.js | 9 ++++-- 5 files changed, 34 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 930a5871a2bae8..2d6a5627a52a44 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -293,7 +293,6 @@ _Parameters_ - _$0_ `Object`: Props. - _$0.children_ `Object`: The block content and style container. - _$0.\_\_unstableContentRef_ `Object`: Ref holding the content scroll container. -- _$0.\_\_experimentalBlockToolbarDisplay_ `string`: The display mode for the block toolbar. ### BlockVerticalAlignmentControl diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index ba96595fe2a523..c3daed7796d71d 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -18,7 +18,6 @@ import { import BlockToolbarPopover from './block-toolbar-popover'; import BlockToolbarBreadcrumb from './block-toolbar-breadcrumb'; import { store as blockEditorStore } from '../../store'; -import BlockToolbar from '../block-toolbar'; import usePopoverScroll from '../block-popover/use-popover-scroll'; import ZoomOutModeInserters from './zoom-out-mode-inserters'; @@ -27,6 +26,7 @@ function selector( select ) { getSelectedBlockClientId, getFirstMultiSelectedBlockClientId, getBlock, + getSettings, hasMultiSelection, __unstableGetEditorMode, isTyping, @@ -39,6 +39,7 @@ function selector( select ) { const editorMode = __unstableGetEditorMode(); return { clientId, + hasFixedToolbar: getSettings().hasFixedToolbar, hasSelectedBlock: clientId && name, isEmptyDefaultBlock: isUnmodifiedDefaultBlock( getBlock( clientId ) || {} @@ -61,19 +62,18 @@ function selector( select ) { * insertion point and a slot for the inline rich text toolbar). Must be wrapped * around the block content and editor styles wrapper or iframe. * - * @param {Object} $0 Props. - * @param {Object} $0.children The block content and style container. - * @param {Object} $0.__unstableContentRef Ref holding the content scroll container. - * @param {string} $0.__experimentalBlockToolbarDisplay The display mode for the block toolbar. + * @param {Object} $0 Props. + * @param {Object} $0.children The block content and style container. + * @param {Object} $0.__unstableContentRef Ref holding the content scroll container. */ export default function BlockTools( { children, __unstableContentRef, - __experimentalBlockToolbarDisplay = 'popover', ...props } ) { const { clientId, + hasFixedToolbar, hasSelectedBlock, isEmptyDefaultBlock, isTyping, @@ -178,9 +178,6 @@ export default function BlockTools( { __unstableContentRef={ __unstableContentRef } /> ) } - { __experimentalBlockToolbarDisplay === 'sticky' && ( - - ) } { showEmptyBlockSideInserter && ( ) } - { __experimentalBlockToolbarDisplay === 'popover' && + { ! hasFixedToolbar && ! showEmptyBlockSideInserter && hasSelectedBlock && ! isEmptyDefaultBlock && @@ -210,14 +207,12 @@ export default function BlockTools( { ) } { /* Used for the inline rich text toolbar. Until this toolbar is combined into BlockToolbar, someone implementing their own BlockToolbar will also need to use this to see the image caption toolbar. */ } - { ! isZoomOutMode && - ( __experimentalBlockToolbarDisplay === 'popover' || - __experimentalBlockToolbarDisplay === 'sticky' ) && ( - - ) } + { ! isZoomOutMode && ! hasFixedToolbar && ( + + ) } { children } { /* Used for inline rich text popovers. */ } =' ); - const isLargeViewport = useViewportMatch( 'large' ); + const isWideViewport = useViewportMatch( 'large' ); + const isLargeViewport = useViewportMatch( 'medium' ); + const { openGeneralSidebar, closeGeneralSidebar, setIsInserterOpened } = useDispatch( editPostStore ); const { createErrorNotice } = useDispatch( noticesStore ); @@ -148,7 +151,6 @@ function Layout() { isRichEditingEnabled, sidebarIsOpened, hasActiveMetaboxes, - hasFixedToolbar, previousShortcut, nextShortcut, hasBlockSelected, @@ -167,8 +169,6 @@ function Layout() { return { showMetaBoxes: select( editorStore ).getRenderingMode() === 'post-only', - hasFixedToolbar: - select( editPostStore ).isFeatureActive( 'fixedToolbar' ), sidebarIsOpened: !! ( select( interfaceStore ).getActiveComplementaryArea( editPostStore.name @@ -219,12 +219,12 @@ function Layout() { if ( sidebarIsOpened && ! isHugeViewport ) { setIsInserterOpened( false ); } - }, [ sidebarIsOpened, isHugeViewport ] ); + }, [ isHugeViewport, setIsInserterOpened, sidebarIsOpened ] ); useEffect( () => { if ( isInserterOpened && ! isHugeViewport ) { closeGeneralSidebar(); } - }, [ isInserterOpened, isHugeViewport ] ); + }, [ closeGeneralSidebar, isInserterOpened, isHugeViewport ] ); // Local state for save panel. // Note 'truthy' callback implies an open panel. @@ -253,9 +253,8 @@ function Layout() { const className = classnames( 'edit-post-layout', 'is-mode-' + mode, { 'is-sidebar-opened': sidebarIsOpened, - 'has-fixed-toolbar': hasFixedToolbar, 'has-metaboxes': hasActiveMetaboxes, - 'is-distraction-free': isDistractionFree && isLargeViewport, + 'is-distraction-free': isDistractionFree && isWideViewport, 'is-entity-save-view-open': !! entitiesSavedStatesCallback, } ); @@ -302,7 +301,7 @@ function Layout() { ) } + { ! isLargeViewport && } { isRichEditingEnabled && mode === 'visual' && ( ) } diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index 229ab58a4e14b0..a3fcbefe8c87e4 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -99,3 +99,9 @@ .edit-post-layout .entities-saved-states__panel-header { height: $header-height + $border-width; } + +@media ( max-width: $break-medium ) { + .block-editor-block-contextual-toolbar.components-accessible-toolbar { + border-top: none; + } +} diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index cff867c3f7a2cb..0abf3328635a86 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -14,6 +14,7 @@ import { SlotFillProvider } from '@wordpress/components'; import { store as coreStore } from '@wordpress/core-data'; import { store as preferencesStore } from '@wordpress/preferences'; import { CommandMenu } from '@wordpress/commands'; +import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -26,6 +27,8 @@ import { unlock } from './lock-unlock'; const { ExperimentalEditorProvider } = unlock( editorPrivateApis ); function Editor( { postId, postType, settings, initialEdits, ...props } ) { + const isLargeViewport = useViewportMatch( 'medium' ); + const { hasFixedToolbar, focusMode, @@ -66,9 +69,9 @@ function Editor( { postId, postType, settings, initialEdits, ...props } ) { getEditorSettings().supportsTemplateMode; const isViewable = getPostType( postType )?.viewable ?? false; const canEditTemplate = canUser( 'create', 'templates' ); - return { - hasFixedToolbar: isFeatureActive( 'fixedToolbar' ), + hasFixedToolbar: + isFeatureActive( 'fixedToolbar' ) || ! isLargeViewport, focusMode: isFeatureActive( 'focusMode' ), isDistractionFree: isFeatureActive( 'distractionFree' ), hasInlineToolbar: isFeatureActive( 'inlineToolbar' ), @@ -86,7 +89,7 @@ function Editor( { postId, postType, settings, initialEdits, ...props } ) { post: postObject, }; }, - [ postType, postId ] + [ postType, postId, isLargeViewport ] ); const { updatePreferredStyleVariations, setIsInserterOpened } = From afca15c8e39fef7d6029dd2f73aeceb57869b6c9 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 1 Dec 2023 14:05:06 -0600 Subject: [PATCH 27/51] Implement hasFixedToolbar setting off isLargeViewport for Widgets Editor --- .../index.js | 27 ++++++------------- .../index.js | 5 +++- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js b/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js index 2efb5fb8808904..e187825f76526c 100644 --- a/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js +++ b/packages/edit-widgets/src/components/widget-areas-block-editor-content/index.js @@ -3,6 +3,7 @@ */ import { BlockList, + BlockToolbar, BlockTools, BlockSelectionClearer, WritingFlow, @@ -22,26 +23,15 @@ import KeyboardShortcuts from '../keyboard-shortcuts'; export default function WidgetAreasBlockEditorContent( { blockEditorSettings, } ) { - const { hasTopToolbar, hasThemeStyles } = useSelect( ( select ) => { - return { - hasTopToolbar: !! select( preferencesStore ).get( - 'core/edit-widgets', - 'fixedToolbar' - ), - hasThemeStyles: !! select( preferencesStore ).get( + const hasThemeStyles = useSelect( + ( select ) => + !! select( preferencesStore ).get( 'core/edit-widgets', 'themeStyles' ), - }; - }, [] ); + [] + ); const isLargeViewport = useViewportMatch( 'medium' ); - let blockToolbarDisplay = 'popover'; - - if ( ! isLargeViewport ) { - blockToolbarDisplay = 'sticky'; - } else if ( hasTopToolbar ) { - blockToolbarDisplay = 'none'; - } const styles = useMemo( () => { return hasThemeStyles ? blockEditorSettings.styles : []; @@ -50,9 +40,8 @@ export default function WidgetAreasBlockEditorContent( { return (
- + { ! isLargeViewport && } + Date: Fri, 1 Dec 2023 14:09:29 -0600 Subject: [PATCH 28/51] Modify block toolbar border css to have fewer overrides --- .../block-editor/src/components/block-toolbar/style.scss | 2 +- packages/edit-post/src/components/layout/style.scss | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index eb7ebaac2cd7b3..49fb399150cd61 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -62,13 +62,13 @@ z-index: z-index(".block-editor-block-popover"); display: block; width: 100%; - // Block UI appearance. background-color: $white; flex-shrink: 3; // Raise the specificity. &.components-accessible-toolbar { + border: none; border-bottom: $border-width solid $gray-200; border-radius: 0; } diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index a3fcbefe8c87e4..229ab58a4e14b0 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -99,9 +99,3 @@ .edit-post-layout .entities-saved-states__panel-header { height: $header-height + $border-width; } - -@media ( max-width: $break-medium ) { - .block-editor-block-contextual-toolbar.components-accessible-toolbar { - border-top: none; - } -} From b2ba337a38e65d435343f8598be6240f5e72f814 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 1 Dec 2023 14:13:51 -0600 Subject: [PATCH 29/51] Update Storybook examples --- storybook/stories/playground/box/index.js | 7 ++++++- storybook/stories/playground/with-undo-redo/index.js | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/storybook/stories/playground/box/index.js b/storybook/stories/playground/box/index.js index e578dfd428904e..c5c7929955771e 100644 --- a/storybook/stories/playground/box/index.js +++ b/storybook/stories/playground/box/index.js @@ -6,6 +6,7 @@ import { registerCoreBlocks } from '@wordpress/block-library'; import { BlockEditorProvider, BlockCanvas, + BlockToolbar, BlockTools, } from '@wordpress/block-editor'; @@ -32,8 +33,12 @@ export default function EditorBox() { value={ blocks } onInput={ updateBlocks } onChange={ updateBlocks } + settings={ { + hasFixedToolbar: true, + } } > - + +
diff --git a/storybook/stories/playground/with-undo-redo/index.js b/storybook/stories/playground/with-undo-redo/index.js index 0bf791355f7fa8..d2a2c120c11d9b 100644 --- a/storybook/stories/playground/with-undo-redo/index.js +++ b/storybook/stories/playground/with-undo-redo/index.js @@ -7,6 +7,7 @@ import { registerCoreBlocks } from '@wordpress/block-library'; import { BlockEditorProvider, BlockCanvas, + BlockToolbar, BlockTools, } from '@wordpress/block-editor'; import { Button } from '@wordpress/components'; @@ -41,6 +42,9 @@ export default function EditorWithUndoRedo() { onChange={ ( blocks, { selection } ) => setValue( { blocks, selection }, false ) } + settings={ { + hasFixedToolbar: true, + } } >
From 91cf32f770c36cd72b2ef781d7cf9e0590f2b271 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 1 Dec 2023 14:32:42 -0600 Subject: [PATCH 30/51] Implemenet customize-widget toolbar modes --- .../components/sidebar-block-editor/index.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/index.js b/packages/customize-widgets/src/components/sidebar-block-editor/index.js index bd66fd3b7d2160..3d09407def9d58 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -7,6 +7,7 @@ import { useSelect } from '@wordpress/data'; import { useMemo, createPortal } from '@wordpress/element'; import { BlockList, + BlockToolbar, BlockTools, BlockInspector, privateApis as blockEditorPrivateApis, @@ -38,6 +39,7 @@ export default function SidebarBlockEditor( { inspector, } ) { const [ isInserterOpened, setIsInserterOpened ] = useInserter( inserter ); + const isMediumViewport = useViewportMatch( 'small' ); const { hasUploadPermissions, isFixedToolbarActive, @@ -78,7 +80,7 @@ export default function SidebarBlockEditor( { ...blockEditorSettings, __experimentalSetIsInserterOpened: setIsInserterOpened, mediaUpload: mediaUploadBlockEditor, - hasFixedToolbar: isFixedToolbarActive, + hasFixedToolbar: isFixedToolbarActive || ! isMediumViewport, keepCaretInsideBlock, __unstableHasCustomAppender: true, }; @@ -86,12 +88,11 @@ export default function SidebarBlockEditor( { hasUploadPermissions, blockEditorSettings, isFixedToolbarActive, + isMediumViewport, keepCaretInsideBlock, setIsInserterOpened, ] ); - const isMediumViewport = useViewportMatch( 'small' ); - if ( isWelcomeGuideActive ) { return ; } @@ -116,14 +117,10 @@ export default function SidebarBlockEditor( { isFixedToolbarActive || ! isMediumViewport } /> - - + { ( isFixedToolbarActive || ! isMediumViewport ) && ( + + ) } + Date: Fri, 1 Dec 2023 14:58:49 -0600 Subject: [PATCH 31/51] Implement edit site toolbar modes --- .../block-editor/use-site-editor-settings.js | 80 ++++++++++--------- .../edit-site/src/components/editor/index.js | 8 +- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index 962cfe09afb720..2deb2d4cb5fa6e 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -1,6 +1,7 @@ /** * WordPress dependencies */ +import { useViewportMatch } from '@wordpress/compose'; import { useDispatch, useSelect } from '@wordpress/data'; import { useMemo } from '@wordpress/element'; import { store as coreStore } from '@wordpress/core-data'; @@ -89,6 +90,7 @@ function useArchiveLabel( templateSlug ) { export function useSpecificEditorSettings() { const { setIsInserterOpened } = useDispatch( editSiteStore ); + const isLargeViewport = useViewportMatch( 'medium' ); const { templateSlug, focusMode, @@ -98,44 +100,46 @@ export function useSpecificEditorSettings() { canvasMode, settings, postWithTemplate, - } = useSelect( ( select ) => { - const { - getEditedPostType, - getEditedPostId, - getEditedPostContext, - getCanvasMode, - getSettings, - } = unlock( select( editSiteStore ) ); - const { get: getPreference } = select( preferencesStore ); - const { getEditedEntityRecord } = select( coreStore ); - const usedPostType = getEditedPostType(); - const usedPostId = getEditedPostId(); - const _record = getEditedEntityRecord( - 'postType', - usedPostType, - usedPostId - ); - const _context = getEditedPostContext(); - return { - templateSlug: _record.slug, - focusMode: !! getPreference( 'core/edit-site', 'focusMode' ), - isDistractionFree: !! getPreference( - 'core/edit-site', - 'distractionFree' - ), - hasFixedToolbar: !! getPreference( - 'core/edit-site', - 'fixedToolbar' - ), - keepCaretInsideBlock: !! getPreference( - 'core/edit-site', - 'keepCaretInsideBlock' - ), - canvasMode: getCanvasMode(), - settings: getSettings(), - postWithTemplate: _context?.postId, - }; - }, [] ); + } = useSelect( + ( select ) => { + const { + getEditedPostType, + getEditedPostId, + getEditedPostContext, + getCanvasMode, + getSettings, + } = unlock( select( editSiteStore ) ); + const { get: getPreference } = select( preferencesStore ); + const { getEditedEntityRecord } = select( coreStore ); + const usedPostType = getEditedPostType(); + const usedPostId = getEditedPostId(); + const _record = getEditedEntityRecord( + 'postType', + usedPostType, + usedPostId + ); + const _context = getEditedPostContext(); + return { + templateSlug: _record.slug, + focusMode: !! getPreference( 'core/edit-site', 'focusMode' ), + isDistractionFree: !! getPreference( + 'core/edit-site', + 'distractionFree' + ), + hasFixedToolbar: + !! getPreference( 'core/edit-site', 'fixedToolbar' ) || + ! isLargeViewport, + keepCaretInsideBlock: !! getPreference( + 'core/edit-site', + 'keepCaretInsideBlock' + ), + canvasMode: getCanvasMode(), + settings: getSettings(), + postWithTemplate: _context?.postId, + }; + }, + [ isLargeViewport ] + ); const archiveLabels = useArchiveLabel( templateSlug ); const defaultRenderingMode = postWithTemplate ? 'template-locked' : 'all'; const defaultEditorSettings = useMemo( () => { diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 5a2f1e2ec4d1a9..c548c8c83239de 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -8,10 +8,11 @@ import classnames from 'classnames'; */ import { useSelect } from '@wordpress/data'; import { Notice } from '@wordpress/components'; -import { useInstanceId } from '@wordpress/compose'; +import { useInstanceId, useViewportMatch } from '@wordpress/compose'; import { store as preferencesStore } from '@wordpress/preferences'; import { BlockBreadcrumb, + BlockToolbar, store as blockEditorStore, privateApis as blockEditorPrivateApis, BlockInspector, @@ -92,6 +93,8 @@ export default function Editor( { listViewToggleElement, isLoading } ) { const { type: editedPostType } = editedPost; + const isLargeViewport = useViewportMatch( 'medium' ); + const { context, contextPost, @@ -232,6 +235,9 @@ export default function Editor( { listViewToggleElement, isLoading } ) { + { ! isLargeViewport && ( + + ) } Date: Fri, 1 Dec 2023 16:05:23 -0600 Subject: [PATCH 32/51] Add docs to the BlockToolbar --- .../block-editor/src/components/block-toolbar/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 9e75a076d4191b..add6e831680bd3 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -36,6 +36,13 @@ import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls'; +/** + * Renders the block toolbar. + * + * @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. + */ const BlockToolbar = ( { hideDragHandle, variant } ) => { const { blockClientId, From 972ce93ecefce109b269c19adccc286c24ebcea2 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 1 Dec 2023 16:08:39 -0600 Subject: [PATCH 33/51] Add hideDragHandle and unstyled variant props to fixed toolbars --- .../src/components/sidebar-block-editor/index.js | 2 +- packages/edit-post/src/components/layout/index.js | 4 +++- packages/edit-site/src/components/editor/index.js | 5 ++++- .../components/widget-areas-block-editor-content/index.js | 4 +++- storybook/stories/playground/box/index.js | 2 +- storybook/stories/playground/with-undo-redo/index.js | 2 +- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/index.js b/packages/customize-widgets/src/components/sidebar-block-editor/index.js index 3d09407def9d58..645d8b3df264e5 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -118,7 +118,7 @@ export default function SidebarBlockEditor( { } /> { ( isFixedToolbarActive || ! isMediumViewport ) && ( - + ) } ) } - { ! isLargeViewport && } + { ! isLargeViewport && ( + + ) } { isRichEditingEnabled && mode === 'visual' && ( ) } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index c548c8c83239de..629a0af28ef409 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -236,7 +236,10 @@ export default function Editor( { listViewToggleElement, isLoading } ) { { ! isLargeViewport && ( - + ) } - { ! isLargeViewport && } + { ! isLargeViewport && ( + + ) } - + diff --git a/storybook/stories/playground/with-undo-redo/index.js b/storybook/stories/playground/with-undo-redo/index.js index d2a2c120c11d9b..cdc529ae8b41f4 100644 --- a/storybook/stories/playground/with-undo-redo/index.js +++ b/storybook/stories/playground/with-undo-redo/index.js @@ -59,7 +59,7 @@ export default function EditorWithUndoRedo() { icon={ redoIcon } label="Redo" /> - +
From df1efbe74ef493504011b562607b13d3efba374d Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 4 Dec 2023 09:13:19 -0600 Subject: [PATCH 34/51] Clarify focusOnMount deprecation comments --- .../block-editor/src/components/navigable-toolbar/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/navigable-toolbar/index.js b/packages/block-editor/src/components/navigable-toolbar/index.js index b18c1050c8f046..fe1090c47061e5 100644 --- a/packages/block-editor/src/components/navigable-toolbar/index.js +++ b/packages/block-editor/src/components/navigable-toolbar/index.js @@ -98,7 +98,7 @@ function useToolbarFocus( { shouldUseKeyboardFocusShortcut, focusEditorOnEscape, } ) { - // Deprecated in 6.5.0 + // focusOnMount deprecated in 6.5.0 const [ initialFocusOnMount ] = useState( focusOnMount ); const { stopTyping } = useDispatch( blockEditorStore ); @@ -116,7 +116,7 @@ function useToolbarFocus( { // Focus on toolbar when pressing alt+F10 when the toolbar is visible. useShortcut( 'core/block-editor/focus-toolbar', focusToolbarViaShortcut ); - // Deprecated in 6.5.0 + // Force toolbar focus on mount deprecated in 6.5.0 useEffect( () => { if ( initialFocusOnMount ) { focusToolbar(); From ed37de4fdb1b173a85f7cb0ddcc0c4a5056e6b69 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 4 Dec 2023 14:29:59 -0600 Subject: [PATCH 35/51] Remove small white underline from parent block button The background for the button was applied to the parent wrapper, and the wrapper also had a border without any border color, so it was bleeding past the button. Removing that file fixes it and doesn't seem to cause any issues. The applied style are provided by the button component now. --- .../src/components/block-parent-selector/style.scss | 11 ----------- .../src/components/block-toolbar/style.scss | 1 + 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 packages/block-editor/src/components/block-parent-selector/style.scss diff --git a/packages/block-editor/src/components/block-parent-selector/style.scss b/packages/block-editor/src/components/block-parent-selector/style.scss deleted file mode 100644 index c5a1869835188c..00000000000000 --- a/packages/block-editor/src/components/block-parent-selector/style.scss +++ /dev/null @@ -1,11 +0,0 @@ -.block-editor-block-parent-selector { - background: $white; - border-radius: $radius-block-ui; - - .block-editor-block-parent-selector__button { - width: $grid-unit-60; - height: $grid-unit-60; - border: $border-width solid $gray-900; - border-radius: $radius-block-ui; - } -} diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index 49fb399150cd61..946bd305f72f94 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -122,6 +122,7 @@ border: 0; padding-right: 6px; padding-left: 6px; + background-color: $white; &::after { content: "\00B7"; From cdeca82b9a357214ddef8ef96a8d172b6ae0ba12 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 4 Dec 2023 16:45:54 -0600 Subject: [PATCH 36/51] Set variant=unstyled as default value for BlockToolbar --- packages/block-editor/src/components/block-toolbar/index.js | 5 +++-- .../src/components/block-tools/block-toolbar-popover.js | 2 +- .../src/components/sidebar-block-editor/index.js | 2 +- packages/edit-post/src/components/header/index.js | 2 +- packages/edit-post/src/components/layout/index.js | 4 +--- packages/edit-site/src/components/editor/index.js | 5 +---- packages/edit-site/src/components/header-edit-mode/index.js | 5 +---- packages/edit-widgets/src/components/header/index.js | 5 +---- .../components/widget-areas-block-editor-content/index.js | 4 +--- storybook/stories/playground/box/index.js | 2 +- storybook/stories/playground/with-undo-redo/index.js | 2 +- 11 files changed, 13 insertions(+), 25 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index add6e831680bd3..ac574554f86575 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -43,7 +43,7 @@ import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls * @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. */ -const BlockToolbar = ( { hideDragHandle, variant } ) => { +const BlockToolbar = ( { hideDragHandle, variant = 'unstyled' } ) => { const { blockClientId, blockClientIds, @@ -142,7 +142,8 @@ const BlockToolbar = ( { hideDragHandle, variant } ) => { className={ classes } /* translators: accessibility text for the block toolbar */ aria-label={ __( 'Block tools' ) } - variant={ variant } + // The variant is applied as "toolbar" when undefined, which is the black border style of the dropdown from the toolbar popover. + variant={ variant === 'highContrast' ? undefined : variant } // 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 } diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index 365212877e33e3..98458f8bf9ca9e 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -45,7 +45,7 @@ export default function BlockToolbarPopover( { resize={ false } { ...popoverProps } > - +
); } diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/index.js b/packages/customize-widgets/src/components/sidebar-block-editor/index.js index 645d8b3df264e5..c2e10bca16ec0b 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -118,7 +118,7 @@ export default function SidebarBlockEditor( { } /> { ( isFixedToolbarActive || ! isMediumViewport ) && ( - + ) } - +
) } - { ! isLargeViewport && ( - - ) } + { ! isLargeViewport && } { isRichEditingEnabled && mode === 'visual' && ( ) } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 629a0af28ef409..295f4ec3cf5c60 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -236,10 +236,7 @@ export default function Editor( { listViewToggleElement, isLoading } ) { { ! isLargeViewport && ( - + ) } - +
- +
- { ! isLargeViewport && ( - - ) } + { ! isLargeViewport && } - + diff --git a/storybook/stories/playground/with-undo-redo/index.js b/storybook/stories/playground/with-undo-redo/index.js index cdc529ae8b41f4..537ea16aade99b 100644 --- a/storybook/stories/playground/with-undo-redo/index.js +++ b/storybook/stories/playground/with-undo-redo/index.js @@ -59,7 +59,7 @@ export default function EditorWithUndoRedo() { icon={ redoIcon } label="Redo" /> - + From 04b42a101a7e22b8af11cc59ecf9c948678e2b03 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 4 Dec 2023 16:51:23 -0600 Subject: [PATCH 37/51] Fix error in variant name --- packages/block-editor/src/components/block-toolbar/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index ac574554f86575..06cedfe6e163e8 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -143,7 +143,7 @@ const BlockToolbar = ( { hideDragHandle, variant = 'unstyled' } ) => { /* 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 === 'highContrast' ? undefined : variant } + variant={ variant === 'toolbar' ? undefined : variant } // 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 } From e842262da7695ea966b89aedb49af32390f026d0 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 4 Dec 2023 17:08:30 -0600 Subject: [PATCH 38/51] Remove deleted scss file from build --- packages/block-editor/src/style.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index a55756ae6f53d7..16de2dfdb71142 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -10,7 +10,6 @@ @import "./components/block-draggable/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-patterns-paging/style.scss"; @import "./components/block-popover/style.scss"; From c74e1c5b6aa99b44cacecac6f7db4b9a04984072 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 5 Dec 2023 10:07:44 -0600 Subject: [PATCH 39/51] Switch BlockToolbar to named function --- packages/block-editor/README.md | 8 ++++++++ .../src/components/block-toolbar/index.js | 14 +++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 2d6a5627a52a44..56ab5f1bd94d93 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -280,10 +280,18 @@ _Returns_ ### BlockToolbar +Renders the block toolbar. + _Related_ - +_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. diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 06cedfe6e163e8..1c2b193a256387 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -39,11 +39,16 @@ import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls /** * 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. */ -const BlockToolbar = ( { hideDragHandle, variant = 'unstyled' } ) => { +export default function BlockToolbar( { + hideDragHandle, + variant = 'unstyled', +} ) { const { blockClientId, blockClientIds, @@ -209,9 +214,4 @@ const BlockToolbar = ( { hideDragHandle, variant = 'unstyled' } ) => {
); -}; - -/** - * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-toolbar/README.md - */ -export default BlockToolbar; +} From d84f0febb8280b1a5e5552d479982482436c8553 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 5 Dec 2023 10:32:33 -0600 Subject: [PATCH 40/51] Deprecate focusOnMount in NavigableToolbar README --- .../block-editor/src/components/navigable-toolbar/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-editor/src/components/navigable-toolbar/README.md b/packages/block-editor/src/components/navigable-toolbar/README.md index 30a4d100195f85..317be48f38faa2 100644 --- a/packages/block-editor/src/components/navigable-toolbar/README.md +++ b/packages/block-editor/src/components/navigable-toolbar/README.md @@ -8,6 +8,8 @@ The component accepts the following props. Props not included in this set will b ## `focusOnMount` +_Note: this prop is deprecated._ + Whether to immediately focus when the component mounts. - Type: `Boolean` From 4d954bd046939b655c34671d8fbbbfdd98856789 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 5 Dec 2023 14:40:59 -0600 Subject: [PATCH 41/51] Show icon label toolbar fixes --- .../src/components/block-toolbar/style.scss | 72 ++++--------------- .../src/components/block-tools/style.scss | 20 ++++-- 2 files changed, 31 insertions(+), 61 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index 946bd305f72f94..d3e5733d34e728 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -96,42 +96,15 @@ width: initial; } - .show-icon-labels & { - .block-editor-block-parent-selector .block-editor-block-parent-selector__button::after { - left: 0; - } - - .block-editor-block-toolbar__block-controls .block-editor-block-mover { - border-left: none; - &::before { - content: ""; - width: $border-width; - margin-top: $grid-unit + $grid-unit-05; - margin-bottom: $grid-unit + $grid-unit-05; - background-color: $gray-300; - position: relative; - } - } - } - - .block-editor-block-parent-selector { - - .block-editor-block-parent-selector__button { - position: relative; - top: -1px; - border: 0; - padding-right: 6px; - padding-left: 6px; - background-color: $white; - - &::after { - content: "\00B7"; - font-size: 16px; - line-height: $grid-unit-40 + $grid-unit-10; - position: absolute; - left: $grid-unit-40 + $grid-unit-15 + 2px; - bottom: $grid-unit-05; - } + body:not(.show-icon-labels) & .block-editor-block-parent-selector__button { + + &::after { + content: "\00B7"; + font-size: 16px; + line-height: $grid-unit-40 + $grid-unit-10; + position: absolute; + left: $grid-unit-40 + $grid-unit-15 + 2px; + bottom: $grid-unit-05; } } } @@ -195,7 +168,6 @@ } // Padding overrides. - .components-accessible-toolbar .components-toolbar-group > div:first-child:last-child > .components-button.has-icon { padding-left: 6px; padding-right: 6px; @@ -211,10 +183,12 @@ } // Parent selector overrides - - .block-editor-block-parent-selector__button { + .block-editor-block-parent-selector .block-editor-block-parent-selector__button { border-top-right-radius: 0; border-bottom-right-radius: 0; + padding-left: $grid-unit-15; + padding-right: $grid-unit-15; + text-wrap: nowrap; .block-editor-block-icon { width: 0; @@ -240,25 +214,17 @@ // Mover overrides. .block-editor-block-toolbar__block-controls .block-editor-block-mover { - border-left: 1px solid $gray-900; + border-left: 1px solid $gray-300; margin-left: 6px; margin-right: -6px; white-space: nowrap; } - .block-editor-block-contextual-toolbar.is-fixed .block-editor-block-toolbar__block-controls .block-editor-block-mover { - border-left-color: $gray-200; - } - .block-editor-block-mover .block-editor-block-mover__drag-handle.has-icon { padding-left: $grid-unit-15; padding-right: $grid-unit-15; } - .block-editor-block-contextual-toolbar.is-fixed .block-editor-block-mover__move-button-container { - border-width: 0; - } - @include break-small() { // Specificity override for https://github.com/WordPress/gutenberg/blob/try/block-toolbar-labels/packages/block-editor/src/components/block-mover/style.scss#L69 .is-up-button.is-up-button.is-up-button { @@ -267,17 +233,9 @@ order: 1; } - .block-editor-block-mover__move-button-container { - border-left: 1px solid $gray-900; - } - .is-down-button.is-down-button.is-down-button { order: 2; } - - .block-editor-block-contextual-toolbar.is-fixed .block-editor-block-mover__move-button-container::before { - background: $gray-300; - } } .block-editor-block-contextual-toolbar .block-editor-block-mover.is-horizontal .block-editor-block-mover-button.block-editor-block-mover-button { @@ -291,7 +249,7 @@ } @include break-medium() { - .block-editor-block-contextual-toolbar.is-fixed { + .block-editor-block-contextual-toolbar { .components-toolbar, .components-toolbar-group { flex-shrink: 0; diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 4632ce01f3c2aa..be072d587b7a81 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -231,19 +231,31 @@ border: 1px solid $gray-900; padding-right: 6px; padding-left: 6px; + background-color: $white; + top: -1px; &::after { content: ""; } } + } - .show-icon-labels & { - position: relative; - left: auto; - top: auto; + // Show Icon Label Styles + .show-icon-labels & { + + .block-editor-block-parent-selector { + position: static; margin-top: -$border-width; margin-left: -$border-width; margin-bottom: -$border-width; + + .block-editor-block-parent-selector__button { + position: static; + } + } + .block-editor-block-mover__move-button-container, + .block-editor-block-toolbar__block-controls .block-editor-block-mover { + border-left: 1px solid $gray-900; } } } From 533f71b41e7fb5523c34448b461dd06f88746b9b Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 5 Dec 2023 16:24:07 -0600 Subject: [PATCH 42/51] Block toolbar show-icon-label css fixes --- .../src/components/block-toolbar/style.scss | 16 +++++++++++----- .../src/components/block-tools/style.scss | 10 ++++------ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index d3e5733d34e728..fedd8e0a604178 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -96,17 +96,23 @@ width: initial; } - body:not(.show-icon-labels) & .block-editor-block-parent-selector__button { + .block-editor-block-parent-selector { + position: relative; + // Parent selector dot divider &::after { content: "\00B7"; - font-size: 16px; - line-height: $grid-unit-40 + $grid-unit-10; position: absolute; - left: $grid-unit-40 + $grid-unit-15 + 2px; - bottom: $grid-unit-05; + font-size: 16px; + right: 0; + bottom: $grid-unit-20; } } + + .block-editor-block-parent-selector__button { + position: relative; + top: -1px; + } } diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index be072d587b7a81..3371d795e6c033 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -226,17 +226,15 @@ position: absolute; left: calc(-#{$grid-unit-60} - #{$grid-unit-10} - #{$border-width}); + &::before { + content: ""; + } + .block-editor-block-parent-selector__button { - position: relative; border: 1px solid $gray-900; padding-right: 6px; padding-left: 6px; background-color: $white; - top: -1px; - - &::after { - content: ""; - } } } From a3511a22be9600a42d60ae1971e85973fad92ff3 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 5 Dec 2023 16:46:21 -0600 Subject: [PATCH 43/51] Top toolbar css fixes --- .../edit-post/src/components/header/style.scss | 16 ++++++++++++++++ .../src/components/header-edit-mode/style.scss | 13 +++++++++++++ .../src/components/header/style.scss | 9 --------- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/packages/edit-post/src/components/header/style.scss b/packages/edit-post/src/components/header/style.scss index 7870da65f092bf..55450ba8f1de28 100644 --- a/packages/edit-post/src/components/header/style.scss +++ b/packages/edit-post/src/components/header/style.scss @@ -216,6 +216,22 @@ } } +.show-icon-labels { + + .edit-post-header__toolbar .block-editor-block-mover { + border-left: none; + + &::before { + content: ""; + width: $border-width; + margin-top: $grid-unit + $grid-unit-05; + margin-bottom: $grid-unit + $grid-unit-05; + background-color: $gray-300; + margin-left: $grid-unit; + } + } +} + .edit-post-header__dropdown { .components-menu-item__button.components-menu-item__button, .components-button.editor-history__undo, diff --git a/packages/edit-site/src/components/header-edit-mode/style.scss b/packages/edit-site/src/components/header-edit-mode/style.scss index 0cfe452805ac37..cbd0a7422b5364 100644 --- a/packages/edit-site/src/components/header-edit-mode/style.scss +++ b/packages/edit-site/src/components/header-edit-mode/style.scss @@ -188,6 +188,19 @@ $header-toolbar-min-width: 335px; .edit-site-header-edit-mode__document-tools .edit-site-header-edit-mode__toolbar > * + * { margin-left: $grid-unit-10; } + + .block-editor-block-mover { + border-left: none; + + &::before { + content: ""; + width: $border-width; + margin-top: $grid-unit + $grid-unit-05; + margin-bottom: $grid-unit + $grid-unit-05; + background-color: $gray-300; + margin-left: $grid-unit; + } + } } .has-fixed-toolbar { diff --git a/packages/edit-widgets/src/components/header/style.scss b/packages/edit-widgets/src/components/header/style.scss index 5a45e7033872f8..2dd4b88eebddfa 100644 --- a/packages/edit-widgets/src/components/header/style.scss +++ b/packages/edit-widgets/src/components/header/style.scss @@ -17,15 +17,6 @@ border-bottom: 0; } - &::after { - content: ""; - width: $border-width; - margin-top: $grid-unit + $grid-unit-05; - margin-bottom: $grid-unit + $grid-unit-05; - background-color: $gray-300; - margin-left: $grid-unit; - } - // Modified group borders .components-toolbar-group, .components-toolbar { From 2dbc7d95bb092fa94946fceec806b0fb3d192202 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 6 Dec 2023 16:56:18 -0600 Subject: [PATCH 44/51] Revert BlockToolbarPopover to mount/unmount instead of show/hide via CSS There was a regression in the typing metric due to the BlockToolbar doing some processing on each keystroke. --- .../src/components/block-toolbar/index.js | 38 +++++++- .../block-tools/block-toolbar-popover.js | 86 ++++++++++++++----- .../src/components/block-tools/index.js | 1 + .../src/components/navigable-toolbar/index.js | 62 ++++++++++--- packages/block-editor/src/private-apis.js | 2 + 5 files changed, 151 insertions(+), 38 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 1c2b193a256387..5eca2384a9384d 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -41,12 +41,18 @@ import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls * * @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. + * @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 default function BlockToolbar( { +export function PrivateBlockToolbar( { hideDragHandle, + focusOnMount, + __experimentalInitialIndex, + __experimentalOnIndexChange, variant = 'unstyled', } ) { const { @@ -149,6 +155,9 @@ export default function BlockToolbar( { 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 } @@ -215,3 +224,24 @@ export default function BlockToolbar( { ); } + +/** + * 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 function BlockToolbar( { hideDragHandle, variant } ) { + return ( + + ); +} diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index 98458f8bf9ca9e..1a57359be17f16 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -2,50 +2,92 @@ * External dependencies */ import classnames from 'classnames'; - /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; - +import { useDispatch } from '@wordpress/data'; +import { useEffect, useRef } from '@wordpress/element'; +import { useShortcut } from '@wordpress/keyboard-shortcuts'; /** * Internal dependencies */ -import { store as blockEditorStore } from '../../store'; -import BlockToolbar from '../block-toolbar'; +import { unlock } from '../../lock-unlock'; import BlockPopover from '../block-popover'; import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; import useSelectedBlockToolProps from './use-selected-block-tool-props'; +import { store as blockEditorStore } from '../../store'; +import { privateApis as blockEditorPrivateApis } from '../../private-apis'; + +const { PrivateBlockToolbar } = unlock( blockEditorPrivateApis ); export default function BlockToolbarPopover( { clientId, + isTyping, __unstableContentRef, } ) { - const isTyping = useSelect( - ( select ) => select( blockEditorStore ).isTyping(), - [] - ); - const { capturingClientId, isInsertionPointVisible, lastClientId } = useSelectedBlockToolProps( clientId ); + // Stores the active toolbar item index so the block toolbar can return focus + // to it when re-mounting. + const initialToolbarItemIndexRef = useRef(); + + useEffect( () => { + // Resets the index whenever the active block changes so this is not + // persisted. See https://github.com/WordPress/gutenberg/pull/25760#issuecomment-717906169 + initialToolbarItemIndexRef.current = undefined; + }, [ clientId ] ); + + const { stopTyping } = useDispatch( blockEditorStore ); + const isToolbarForced = useRef( false ); + + useShortcut( + 'core/block-editor/focus-toolbar', + () => { + isToolbarForced.current = true; + stopTyping( true ); + }, + { + isDisabled: false, + } + ); + + useEffect( () => { + isToolbarForced.current = false; + } ); + const popoverProps = useBlockToolbarPopoverProps( { contentElement: __unstableContentRef?.current, clientId, } ); return ( - - - + ! isTyping && ( + + { + initialToolbarItemIndexRef.current = index; + } } + variant="toolbar" + /> + + ) ); } diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index c3daed7796d71d..8b0fc778863290 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -194,6 +194,7 @@ export default function BlockTools( { ) } diff --git a/packages/block-editor/src/components/navigable-toolbar/index.js b/packages/block-editor/src/components/navigable-toolbar/index.js index fe1090c47061e5..8954f7e17f132e 100644 --- a/packages/block-editor/src/components/navigable-toolbar/index.js +++ b/packages/block-editor/src/components/navigable-toolbar/index.js @@ -9,7 +9,7 @@ import { useEffect, useCallback, } from '@wordpress/element'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; import { focus } from '@wordpress/dom'; import { useShortcut } from '@wordpress/keyboard-shortcuts'; @@ -25,6 +25,14 @@ function hasOnlyToolbarItem( elements ) { return ! elements.some( ( element ) => ! ( dataProp in element.dataset ) ); } +function getAllToolbarItemsIn( container ) { + return Array.from( container.querySelectorAll( '[data-toolbar-item]' ) ); +} + +function hasFocusWithin( container ) { + return container.contains( container.ownerDocument.activeElement ); +} + function focusFirstTabbableIn( container ) { const [ firstTabbable ] = focus.tabbable.find( container ); @@ -95,12 +103,14 @@ function useToolbarFocus( { toolbarRef, focusOnMount, isAccessibleToolbar, + defaultIndex, + onIndexChange, shouldUseKeyboardFocusShortcut, focusEditorOnEscape, } ) { - // focusOnMount deprecated in 6.5.0 + // Make sure we don't use modified versions of this prop. const [ initialFocusOnMount ] = useState( focusOnMount ); - const { stopTyping } = useDispatch( blockEditorStore ); + const [ initialIndex ] = useState( defaultIndex ); const focusToolbar = useCallback( () => { focusFirstTabbableIn( toolbarRef.current ); @@ -108,7 +118,6 @@ function useToolbarFocus( { const focusToolbarViaShortcut = () => { if ( shouldUseKeyboardFocusShortcut ) { - stopTyping( true ); // This matches the behavior of the Tab/Escape observe typing to stopTyping. Should we add this shortcut there? focusToolbar(); } }; @@ -116,13 +125,45 @@ function useToolbarFocus( { // Focus on toolbar when pressing alt+F10 when the toolbar is visible. useShortcut( 'core/block-editor/focus-toolbar', focusToolbarViaShortcut ); - // Force toolbar focus on mount deprecated in 6.5.0 useEffect( () => { if ( initialFocusOnMount ) { focusToolbar(); } }, [ isAccessibleToolbar, initialFocusOnMount, focusToolbar ] ); + useEffect( () => { + // Store ref so we have access on useEffect cleanup: https://legacy.reactjs.org/blog/2020/08/10/react-v17-rc.html#effect-cleanup-timing + const navigableToolbarRef = toolbarRef.current; + // If initialIndex is passed, we focus on that toolbar item when the + // toolbar gets mounted and initial focus is not forced. + // We have to wait for the next browser paint because block controls aren't + // rendered right away when the toolbar gets mounted. + let raf = 0; + if ( ! initialFocusOnMount ) { + raf = window.requestAnimationFrame( () => { + const items = getAllToolbarItemsIn( navigableToolbarRef ); + const index = initialIndex || 0; + if ( items[ index ] && hasFocusWithin( navigableToolbarRef ) ) { + items[ index ].focus( { + // When focusing newly mounted toolbars, + // the position of the popover is often not right on the first render + // This prevents the layout shifts when focusing the dialogs. + preventScroll: true, + } ); + } + } ); + } + return () => { + window.cancelAnimationFrame( raf ); + if ( ! onIndexChange || ! navigableToolbarRef ) return; + // When the toolbar element is unmounted and onIndexChange is passed, we + // pass the focused toolbar item index so it can be hydrated later. + const items = getAllToolbarItemsIn( navigableToolbarRef ); + const index = items.findIndex( ( item ) => item.tabIndex === 0 ); + onIndexChange( index ); + }; + }, [ initialIndex, initialFocusOnMount, onIndexChange, toolbarRef ] ); + const { lastFocus } = useSelect( ( select ) => { const { getLastFocus } = select( blockEditorStore ); return { @@ -159,21 +200,18 @@ export default function NavigableToolbar( { focusOnMount, focusEditorOnEscape = false, shouldUseKeyboardFocusShortcut = true, + __experimentalInitialIndex: initialIndex, + __experimentalOnIndexChange: onIndexChange, ...props } ) { const toolbarRef = useRef(); const isAccessibleToolbar = useIsAccessibleToolbar( toolbarRef ); - if ( focusOnMount ) { - deprecated( 'The focusOnMount prop', { - since: '6.5', - version: '6.6', - } ); - } - useToolbarFocus( { toolbarRef, focusOnMount, + defaultIndex: initialIndex, + onIndexChange, isAccessibleToolbar, shouldUseKeyboardFocusShortcut, focusEditorOnEscape, diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 9837c206487bea..95bb189708cc73 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -8,6 +8,7 @@ import { getRichTextValues } from './components/rich-text/get-rich-text-values'; import { kebabCase } from './utils/object'; import ResizableBoxPopover from './components/resizable-box-popover'; import { ComposedPrivateInserter as PrivateInserter } from './components/inserter'; +import { PrivateBlockToolbar } from './components/block-toolbar'; import { PrivateListView } from './components/list-view'; import BlockInfo from './components/block-info-slot-fill'; import { useShouldContextualToolbarShow } from './utils/use-should-contextual-toolbar-show'; @@ -37,6 +38,7 @@ lock( privateApis, { getDuotoneFilter, getRichTextValues, kebabCase, + PrivateBlockToolbar, PrivateInserter, PrivateListView, ResizableBoxPopover, From 78fe5912456f146551d0393a82209283050dc30d Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 6 Dec 2023 22:37:54 -0600 Subject: [PATCH 45/51] Fix mistake around unlocking PrivateBlockToolbar within same package --- .../src/components/block-tools/block-toolbar-popover.js | 5 +---- packages/block-editor/src/private-apis.js | 2 -- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js index 1a57359be17f16..a50e5dc42b3712 100644 --- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js +++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js @@ -11,14 +11,11 @@ import { useShortcut } from '@wordpress/keyboard-shortcuts'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; import BlockPopover from '../block-popover'; import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; import useSelectedBlockToolProps from './use-selected-block-tool-props'; import { store as blockEditorStore } from '../../store'; -import { privateApis as blockEditorPrivateApis } from '../../private-apis'; - -const { PrivateBlockToolbar } = unlock( blockEditorPrivateApis ); +import { PrivateBlockToolbar } from '../block-toolbar'; export default function BlockToolbarPopover( { clientId, diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 95bb189708cc73..9837c206487bea 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -8,7 +8,6 @@ import { getRichTextValues } from './components/rich-text/get-rich-text-values'; import { kebabCase } from './utils/object'; import ResizableBoxPopover from './components/resizable-box-popover'; import { ComposedPrivateInserter as PrivateInserter } from './components/inserter'; -import { PrivateBlockToolbar } from './components/block-toolbar'; import { PrivateListView } from './components/list-view'; import BlockInfo from './components/block-info-slot-fill'; import { useShouldContextualToolbarShow } from './utils/use-should-contextual-toolbar-show'; @@ -38,7 +37,6 @@ lock( privateApis, { getDuotoneFilter, getRichTextValues, kebabCase, - PrivateBlockToolbar, PrivateInserter, PrivateListView, ResizableBoxPopover, From 528665ab0364a351969eef0d230595f7c35f1b33 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 6 Dec 2023 22:39:21 -0600 Subject: [PATCH 46/51] Update is-typing test to check for toBeHidden and toBeVisible --- test/e2e/specs/editor/various/is-typing.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/e2e/specs/editor/various/is-typing.spec.js b/test/e2e/specs/editor/various/is-typing.spec.js index 583f1ec97c725e..8063f688409c4e 100644 --- a/test/e2e/specs/editor/various/is-typing.spec.js +++ b/test/e2e/specs/editor/various/is-typing.spec.js @@ -22,19 +22,19 @@ test.describe( 'isTyping', () => { ); // Toolbar Popover should not be showing - await expect( blockToolbarPopover ).toHaveCSS( 'opacity', '0' ); + await expect( blockToolbarPopover ).toBeHidden(); // Moving the mouse shows the toolbar. await editor.showBlockToolbar(); // Toolbar Popover is visible. - await expect( blockToolbarPopover ).toHaveCSS( 'opacity', '1' ); + await expect( blockToolbarPopover ).toBeVisible(); // Typing again hides the toolbar await page.keyboard.type( ' and continue' ); // Toolbar Popover is hidden again - await expect( blockToolbarPopover ).toHaveCSS( 'opacity', '0' ); + await expect( blockToolbarPopover ).toBeHidden(); } ); test( 'should not close the dropdown when typing in it', async ( { From d78f3731590d3939f8269b0612e0276d08319b35 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 7 Dec 2023 10:08:38 -0600 Subject: [PATCH 47/51] Remove unused .is-hidden from CSS show/hide toolbar revert --- .../block-editor/src/components/block-popover/style.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/style.scss b/packages/block-editor/src/components/block-popover/style.scss index 347053f628b8a9..e393e77c63b056 100644 --- a/packages/block-editor/src/components/block-popover/style.scss +++ b/packages/block-editor/src/components/block-popover/style.scss @@ -22,11 +22,6 @@ pointer-events: all; } } - - &.is-hidden { - opacity: 0; - z-index: -1; - } } .components-popover.block-editor-block-popover__inbetween { From 316de06e80b35b3b29ecc3f5d0b62c1ebaa1f5df Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 7 Dec 2023 10:27:18 -0600 Subject: [PATCH 48/51] Refactor to isDefaultEditingMode --- .../src/components/block-toolbar/index.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 5eca2384a9384d..7a65a6dceec277 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -58,7 +58,7 @@ export function PrivateBlockToolbar( { const { blockClientId, blockClientIds, - blockEditingMode, + isDefaultEditingMode, blockType, hasParents, isValid, @@ -81,10 +81,12 @@ export function PrivateBlockToolbar( { const firstParentClientId = parents[ parents.length - 1 ]; const parentBlockName = getBlockName( firstParentClientId ); const parentBlockType = getBlockType( parentBlockName ); + const _isDefaultEditingMode = + getBlockEditingMode( selectedBlockClientId ) === 'default'; return { blockClientId: selectedBlockClientId, blockClientIds: selectedBlockClientIds, - blockEditingMode: getBlockEditingMode( selectedBlockClientId ), + isDefaultEditingMode: _isDefaultEditingMode, blockType: selectedBlockClientId && getBlockType( getBlockName( selectedBlockClientId ) ), @@ -105,8 +107,8 @@ export function PrivateBlockToolbar( { '__experimentalParentSelector', true ) && - selectedBlockClientIds.length <= 1 && - getBlockEditingMode( selectedBlockClientId ) === 'default', + selectedBlockClientIds.length === 1 && + _isDefaultEditingMode, }; }, [] ); @@ -128,7 +130,7 @@ export function PrivateBlockToolbar( { if ( ! isToolbarEnabled || - ( blockEditingMode !== 'default' && ! hasAnyBlockControls ) + ( ! isDefaultEditingMode && ! hasAnyBlockControls ) ) { return null; } @@ -165,9 +167,9 @@ export function PrivateBlockToolbar( {
{ ! isMultiToolbar && isLargeViewport && - blockEditingMode === 'default' && } + isDefaultEditingMode && } { ( shouldShowVisualToolbar || isMultiToolbar ) && - blockEditingMode === 'default' && ( + isDefaultEditingMode && (
) } - { blockEditingMode === 'default' && ( + { isDefaultEditingMode && ( ) }
From 794bd7e051a71989dc6b5e2194d5ba1b8b010f4b Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 7 Dec 2023 10:36:46 -0600 Subject: [PATCH 49/51] Refactor showParentSelector and shouldShowVisualToolbar --- .../src/components/block-toolbar/index.js | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 7a65a6dceec277..7bb52a7e8f0906 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -60,9 +60,7 @@ export function PrivateBlockToolbar( { blockClientIds, isDefaultEditingMode, blockType, - hasParents, - isValid, - isVisual, + shouldShowVisualToolbar, showParentSelector, } = useSelect( ( select ) => { const { @@ -83,6 +81,12 @@ export function PrivateBlockToolbar( { 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, @@ -91,13 +95,7 @@ export function PrivateBlockToolbar( { selectedBlockClientId && getBlockType( getBlockName( selectedBlockClientId ) ), - hasParents: parents.length, - isValid: selectedBlockClientIds.every( ( id ) => - isBlockValid( id ) - ), - isVisual: selectedBlockClientIds.every( - ( id ) => getBlockMode( id ) === 'visual' - ), + shouldShowVisualToolbar: isValid && isVisual, rootClientId: blockRootClientId, showParentSelector: parentBlockType && @@ -135,14 +133,13 @@ export function PrivateBlockToolbar( { return null; } - const shouldShowVisualToolbar = isValid && isVisual; const isMultiToolbar = blockClientIds.length > 1; const isSynced = isReusableBlock( blockType ) || isTemplatePart( blockType ); // Shifts the toolbar to make room for the parent block selector. const classes = classnames( 'block-editor-block-contextual-toolbar', { - 'has-parent': hasParents && showParentSelector, + 'has-parent': showParentSelector, } ); const innerClasses = classnames( 'block-editor-block-toolbar', { From 0dd53fa5c291e6bdfbf3f6a3ba7720781464bd33 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 7 Dec 2023 12:36:50 -0600 Subject: [PATCH 50/51] Refactor names and selector return in block tools The naming was inconsistent and confusing. showBlockToolbar being true did not mean the block toolbar would show. Similarly for showBreadcrumb. Refactored so if showBlockToolbar is true, it will show the block toolbar popover. --- .../src/components/block-tools/index.js | 74 ++++++++++--------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 8b0fc778863290..969f36d878b875 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -37,23 +37,34 @@ function selector( select ) { 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, - hasSelectedBlock: clientId && name, - isEmptyDefaultBlock: isUnmodifiedDefaultBlock( - getBlock( clientId ) || {} - ), isTyping: isTyping(), isZoomOutMode: editorMode === 'zoom-out', - showEmptyBlockSideInserter: - clientId && - ! isTyping() && - editorMode === 'edit' && - isUnmodifiedDefaultBlock( { name, attributes } ), - shouldShowBreadcrumb: - ! hasMultiSelection() && - ( editorMode === 'navigation' || editorMode === 'zoom-out' ), + showEmptyBlockSideInserter: _showEmptyBlockSideInserter, + showBreadcrumb: ! _showEmptyBlockSideInserter && maybeShowBreadcrumb, + showBlockToolbar: + ! getSettings().hasFixedToolbar && + ! _showEmptyBlockSideInserter && + hasSelectedBlock && + ! isEmptyDefaultBlock && + ! maybeShowBreadcrumb, }; } @@ -74,12 +85,11 @@ export default function BlockTools( { const { clientId, hasFixedToolbar, - hasSelectedBlock, - isEmptyDefaultBlock, isTyping, isZoomOutMode, showEmptyBlockSideInserter, - shouldShowBreadcrumb, + showBreadcrumb, + showBlockToolbar, } = useSelect( selector, [] ); const isMatch = useShortcutEventMatch(); const { getSelectedBlockClientIds, getBlockRootClientId } = @@ -186,26 +196,20 @@ export default function BlockTools( { /> ) } - { ! hasFixedToolbar && - ! showEmptyBlockSideInserter && - hasSelectedBlock && - ! isEmptyDefaultBlock && - ! shouldShowBreadcrumb && ( - - ) } - - { ! showEmptyBlockSideInserter && - hasSelectedBlock && - shouldShowBreadcrumb && ( - - ) } + { showBlockToolbar && ( + + ) } + + { showBreadcrumb && ( + + ) } { /* Used for the inline rich text toolbar. Until this toolbar is combined into BlockToolbar, someone implementing their own BlockToolbar will also need to use this to see the image caption toolbar. */ } { ! isZoomOutMode && ! hasFixedToolbar && ( From 58afab910dca851af5585889b9e95474ef0edd72 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 7 Dec 2023 12:39:40 -0600 Subject: [PATCH 51/51] Remove unnecessary flex-shrink from fixed toolbar --- .../src/components/block-toolbar/style.scss | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index fedd8e0a604178..85020cea2aa23f 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -254,16 +254,6 @@ flex-shrink: 1; } - @include break-medium() { - .block-editor-block-contextual-toolbar { - .components-toolbar, - .components-toolbar-group { - flex-shrink: 0; - } - } - } - - .block-editor-rich-text__inline-format-toolbar-group { .components-button + .components-button { margin-left: 6px;