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 3d02a27479586..e453292095720 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 87cfcad1cf9f1..0fa1e9b7b9c95 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 432a7374f612b..6be586196f737 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 767d01a03c191..ce30594e23b04 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 ); }