diff --git a/packages/block-editor/src/components/block-list/block-contextual-toolbar.js b/packages/block-editor/src/components/block-list/block-contextual-toolbar.js
index 3d02a274795862..e4532920957200 100644
--- a/packages/block-editor/src/components/block-list/block-contextual-toolbar.js
+++ b/packages/block-editor/src/components/block-list/block-contextual-toolbar.js
@@ -1,3 +1,8 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
/**
* WordPress dependencies
*/
@@ -12,10 +17,12 @@ import NavigableToolbar from '../navigable-toolbar';
import { BlockToolbar } from '../';
function BlockContextualToolbar( { focusOnMount, ...props } ) {
- const { blockType } = useSelect( ( select ) => {
- const { getBlockName, getSelectedBlockClientIds } = select(
- 'core/block-editor'
- );
+ const { blockType, hasParents } = useSelect( ( select ) => {
+ const {
+ getBlockName,
+ getBlockParents,
+ getSelectedBlockClientIds,
+ } = select( 'core/block-editor' );
const { getBlockType } = select( blocksStore );
const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
@@ -23,6 +30,7 @@ function BlockContextualToolbar( { focusOnMount, ...props } ) {
blockType:
selectedBlockClientId &&
getBlockType( getBlockName( selectedBlockClientId ) ),
+ hasParents: getBlockParents( selectedBlockClientId ).length,
};
}, [] );
if ( blockType ) {
@@ -30,11 +38,17 @@ function BlockContextualToolbar( { focusOnMount, ...props } ) {
return null;
}
}
+
+ // Shifts the toolbar to make room for the parent block selector.
+ const classes = classnames( 'block-editor-block-contextual-toolbar', {
+ 'has-parent': hasParents,
+ } );
+
return (
{
- const {
- getBlockName,
- getBlockParents,
- getSelectedBlockClientId,
- } = select( 'core/block-editor' );
- const { hasBlockSupport } = select( blocksStore );
- const selectedBlockClientId = getSelectedBlockClientId();
- const parents = getBlockParents( selectedBlockClientId );
- const _firstParentClientId = parents[ parents.length - 1 ];
- const parentBlockName = getBlockName( _firstParentClientId );
- const _parentBlockType = getBlockType( parentBlockName );
- return {
- parentBlockType: _parentBlockType,
- firstParentClientId: _firstParentClientId,
- shouldHide: ! hasBlockSupport(
- _parentBlockType,
- '__experimentalParentSelector',
- true
- ),
- };
- },
- []
+ const { selectBlock, toggleBlockHighlight } = useDispatch(
+ 'core/block-editor'
);
+ const {
+ parentBlockType,
+ firstParentClientId,
+ shouldHide,
+ hasReducedUI,
+ } = useSelect( ( select ) => {
+ const {
+ getBlockName,
+ getBlockParents,
+ getSelectedBlockClientId,
+ getSettings,
+ } = select( 'core/block-editor' );
+ const { hasBlockSupport } = select( blocksStore );
+ const selectedBlockClientId = getSelectedBlockClientId();
+ const parents = getBlockParents( selectedBlockClientId );
+ const _firstParentClientId = parents[ parents.length - 1 ];
+ const parentBlockName = getBlockName( _firstParentClientId );
+ const _parentBlockType = getBlockType( parentBlockName );
+ const settings = getSettings();
+ return {
+ parentBlockType: _parentBlockType,
+ firstParentClientId: _firstParentClientId,
+ shouldHide: ! hasBlockSupport(
+ _parentBlockType,
+ '__experimentalParentSelector',
+ true
+ ),
+ hasReducedUI: settings.hasReducedUI,
+ };
+ }, [] );
+
+ // Allows highlighting the parent block outline when focusing or hovering
+ // the parent block selector within the child.
+ const nodeRef = useRef();
+ const { gestures: showMoversGestures } = useShowMoversGestures( {
+ ref: nodeRef,
+ onChange( isFocused ) {
+ if ( isFocused && hasReducedUI ) {
+ return;
+ }
+ toggleBlockHighlight( firstParentClientId, isFocused );
+ },
+ } );
if ( shouldHide ) {
return null;
@@ -54,13 +76,15 @@ export default function BlockParentSelector() {
selectBlock( firstParentClientId ) }
label={ sprintf(
/* translators: %s: Name of the block's parent. */
- __( 'Select parent (%s)' ),
+ __( 'Select %s' ),
parentBlockType.title
) }
showTooltip
diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js
index 87cfcad1cf9f1a..0fa1e9b7b9c95f 100644
--- a/packages/block-editor/src/components/block-toolbar/index.js
+++ b/packages/block-editor/src/components/block-toolbar/index.js
@@ -64,9 +64,10 @@ export default function BlockToolbar( { hideDragHandle } ) {
};
}, [] );
+ // Handles highlighting the current block outline on hover or focus of the
+ // block type toolbar area.
const { toggleBlockHighlight } = useDispatch( 'core/block-editor' );
const nodeRef = useRef();
-
const { showMovers, gestures: showMoversGestures } = useShowMoversGestures(
{
ref: nodeRef,
@@ -79,6 +80,8 @@ export default function BlockToolbar( { hideDragHandle } ) {
}
);
+ // Account for the cases where the block toolbar is rendered within the
+ // header area and not contextually to the block.
const displayHeaderToolbar =
useViewportMatch( 'medium', '<' ) || hasFixedToolbar;
@@ -104,12 +107,10 @@ export default function BlockToolbar( { hideDragHandle } ) {
return (
+ { ! isMultiToolbar && ! displayHeaderToolbar && (
+
+ ) }
- { ! isMultiToolbar && (
-
-
-
- ) }
{ ( shouldShowVisualToolbar || isMultiToolbar ) && (
diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss
index 432a7374f612bb..6be586196f737b 100644
--- a/packages/block-editor/src/components/block-toolbar/style.scss
+++ b/packages/block-editor/src/components/block-toolbar/style.scss
@@ -44,6 +44,16 @@
}
}
+.block-editor-block-contextual-toolbar.has-parent {
+ margin-left: calc(#{$grid-unit-60} + #{$grid-unit-10});
+}
+
+.block-editor-block-parent-selector {
+ position: absolute;
+ top: -$border-width;
+ left: calc(-#{$grid-unit-60} - #{$grid-unit-10} - #{$border-width});
+}
+
// Block controls.
.block-editor-block-toolbar__block-controls {
// The !important modifier should be removed when https://github.com/WordPress/gutenberg/issues/24898 refactors the spacing grid.
@@ -91,22 +101,6 @@
}
}
-.block-editor-block-toolbar__block-parent-selector-wrapper {
- position: absolute;
- top: -1px;
- left: -1px;
- opacity: 0;
- transition: all 60ms linear;
- z-index: -1; // This makes it slide out from underneath the toolbar.
-
- @include reduce-motion("transition");
-
- .is-showing-movers & {
- opacity: 1;
- transform: translateY(-($block-toolbar-height + $grid-unit-15));
- }
-}
-
.show-icon-labels {
.block-editor-block-toolbar {
.components-button.has-icon {
diff --git a/packages/e2e-tests/specs/editor/various/toolbar-roving-tabindex.test.js b/packages/e2e-tests/specs/editor/various/toolbar-roving-tabindex.test.js
index 767d01a03c191b..ce30594e23b041 100644
--- a/packages/e2e-tests/specs/editor/various/toolbar-roving-tabindex.test.js
+++ b/packages/e2e-tests/specs/editor/various/toolbar-roving-tabindex.test.js
@@ -49,7 +49,7 @@ async function testGroupKeyboardNavigation(
await page.keyboard.press( 'Tab' );
await expectLabelToHaveFocus( currentBlockLabel );
await pressKeyWithModifier( 'shift', 'Tab' );
- await expectLabelToHaveFocus( 'Select parent (Group)' );
+ await expectLabelToHaveFocus( 'Select Group' );
await page.keyboard.press( 'ArrowRight' );
await expectLabelToHaveFocus( currentBlockTitle );
}