From a1ccf422e1d54598d69d0fd02a6991a2f85366e3 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 10 Nov 2023 16:09:15 -0600 Subject: [PATCH] Render Selected Block Tools in Header when using Top Toolbar (#55787) The Top Toolbar was relying on position: absolute; CSS and layoutEffect calculations to display the selected block tools visually within the top toolbar. This PR places it in the header DOM where we want it, allowing us to use native CSS and DOM flow to improve accessibility (tab order matches visual order) and have more maintainable code. * Imports `` via private-api and the for image captions to the edit site, edit post, edit widgets, and customize widget headers. * Removes position: absolute; and layoutEffect block toolbar positioning hacks. * CSS for the top toolbar to use flex-shrink and overflow-x: hidden; to allow for the block toolbar to fit its current space and scroll to reveal the hidden tools. * With top toolbar mode, Shift+Tab does not go directly to the toolbar but the first tabstop outside of the editor. Co-authored-by: Alex Lende Co-authored-by: Andrei Draganescu --- .../src/components/block-toolbar/style.scss | 8 + .../block-tools/block-contextual-toolbar.js | 223 ++++-------------- .../src/components/block-tools/index.js | 30 ++- .../block-tools/selected-block-tools.js | 16 +- .../src/components/block-tools/style.scss | 10 - .../src/components/navigable-toolbar/index.js | 30 +-- packages/block-editor/src/private-apis.js | 2 + .../src/components/header/index.js | 29 ++- packages/customize-widgets/src/style.scss | 31 --- .../header/document-actions/index.js | 11 +- .../components/header/header-toolbar/index.js | 6 +- .../edit-post/src/components/header/index.js | 121 ++++++++-- .../src/components/header/style.scss | 33 ++- .../src/components/layout/style.scss | 11 - .../src/components/visual-editor/style.scss | 89 ------- .../src/components/block-editor/style.scss | 87 ------- .../header-edit-mode/document-tools/index.js | 55 ++--- .../src/components/header-edit-mode/index.js | 85 ++++++- .../components/header-edit-mode/style.scss | 37 ++- .../edit-site/src/components/layout/index.js | 1 + .../src/components/layout/style.scss | 17 -- .../src/components/header/index.js | 36 ++- .../src/components/header/style.scss | 10 + .../src/components/layout/style.scss | 12 - .../style.scss | 98 -------- .../editor/various/navigable-toolbar.spec.js | 149 +++++++++++- 26 files changed, 578 insertions(+), 659 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index eef1678e2dfab..3f8a7057aef84 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -56,6 +56,14 @@ } } +.block-editor-block-contextual-toolbar.is-fixed { + 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 { 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 5ba71bee88987..9d9f3edc5442f 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 @@ -7,22 +7,8 @@ import classnames from 'classnames'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { - forwardRef, - useLayoutEffect, - useEffect, - useRef, - useState, -} from '@wordpress/element'; import { hasBlockSupport, store as blocksStore } from '@wordpress/blocks'; import { useSelect } from '@wordpress/data'; -import { - ToolbarItem, - ToolbarButton, - ToolbarGroup, -} from '@wordpress/components'; -import { next, previous } from '@wordpress/icons'; -import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -32,141 +18,46 @@ import BlockToolbar from '../block-toolbar'; import { store as blockEditorStore } from '../../store'; import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls'; -function UnforwardedBlockContextualToolbar( - { focusOnMount, isFixed, ...props }, - ref -) { - // When the toolbar is fixed it can be collapsed - const [ isCollapsed, setIsCollapsed ] = useState( false ); - const toolbarButtonRef = useRef(); - - const isLargeViewport = useViewportMatch( 'medium' ); - 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', - }; - }, [] ); - - useEffect( () => { - setIsCollapsed( false ); - }, [ selectedBlockClientId ] ); - - const isLargerThanTabletViewport = useViewportMatch( 'large', '>=' ); - const isFullscreen = - document.body.classList.contains( 'is-fullscreen-mode' ); - - /** - * The following code is a workaround to fix the width of the toolbar - * it should be removed when the toolbar will be rendered inline - * FIXME: remove this layout effect when the toolbar is no longer - * absolutely positioned - */ - useLayoutEffect( () => { - // don't do anything if not fixed toolbar - if ( ! isFixed ) { - return; - } - - const blockToolbar = document.querySelector( - '.block-editor-block-contextual-toolbar' - ); - - if ( ! blockToolbar ) { - return; - } - - if ( ! blockType ) { - blockToolbar.style.width = 'initial'; - return; - } - - if ( ! isLargerThanTabletViewport ) { - // set the width of the toolbar to auto - blockToolbar.style = {}; - return; - } - - if ( isCollapsed ) { - // set the width of the toolbar to auto - blockToolbar.style.width = 'auto'; - return; - } - - // get the width of the pinned items in the post editor or widget editor - const pinnedItems = document.querySelector( - '.edit-post-header__settings, .edit-widgets-header__actions' - ); - // get the width of the left header in the site editor - const leftHeader = document.querySelector( - '.edit-site-header-edit-mode__end' - ); - - const computedToolbarStyle = window.getComputedStyle( blockToolbar ); - const computedPinnedItemsStyle = pinnedItems - ? window.getComputedStyle( pinnedItems ) - : false; - const computedLeftHeaderStyle = leftHeader - ? window.getComputedStyle( leftHeader ) - : false; - - const marginLeft = parseFloat( computedToolbarStyle.marginLeft ); - const pinnedItemsWidth = computedPinnedItemsStyle - ? parseFloat( computedPinnedItemsStyle.width ) - : 0; - const leftHeaderWidth = computedLeftHeaderStyle - ? parseFloat( computedLeftHeaderStyle.width ) - : 0; - - // set the new witdth of the toolbar - blockToolbar.style.width = `calc(100% - ${ - leftHeaderWidth + - pinnedItemsWidth + - marginLeft + - ( pinnedItems || leftHeader ? 2 : 0 ) + // Prevents button focus border from being cut off - ( isFullscreen ? 0 : 160 ) // the width of the admin sidebar expanded - }px)`; - }, [ - isFixed, - isLargerThanTabletViewport, - isCollapsed, - isFullscreen, - blockType, - ] ); +export default function BlockContextualToolbar( { + focusOnMount, + isFixed, + ...props +} ) { + const { blockType, blockEditingMode, hasParents, showParentSelector } = + 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 && @@ -183,12 +74,10 @@ function UnforwardedBlockContextualToolbar( const classes = classnames( 'block-editor-block-contextual-toolbar', { 'has-parent': hasParents && showParentSelector, 'is-fixed': isFixed, - 'is-collapsed': isCollapsed, } ); return ( - { ! isCollapsed && } - { isFixed && isLargeViewport && blockType && ( - - { - setIsCollapsed( ( collapsed ) => ! collapsed ); - toolbarButtonRef.current.focus(); - } } - label={ - isCollapsed - ? __( 'Show block tools' ) - : __( 'Hide block tools' ) - } - /> - - ) } + ); } - -export const BlockContextualToolbar = forwardRef( - UnforwardedBlockContextualToolbar -); - -export default BlockContextualToolbar; diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 696299689d185..bc2729fbb1599 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -88,8 +88,6 @@ export default function BlockTools( { moveBlocksDown, } = useDispatch( blockEditorStore ); - const selectedBlockToolsRef = useRef( null ); - function onKeyDown( event ) { if ( event.defaultPrevented ) return; @@ -132,7 +130,7 @@ export default function BlockTools( { insertBeforeBlock( clientIds[ 0 ] ); } } else if ( isMatch( 'core/block-editor/unselect', event ) ) { - if ( selectedBlockToolsRef?.current?.contains( event.target ) ) { + if ( event.target.closest( '[role=toolbar]' ) ) { // This shouldn't be necessary, but we have a combination of a few things all combining to create a situation where: // - Because the block toolbar uses createPortal to populate the block toolbar fills, we can't rely on the React event bubbling to hit the onKeyDown listener for the block toolbar // - Since we can't use the React tree, we use the DOM tree which _should_ handle the event bubbling correctly from a `createPortal` element. @@ -164,6 +162,12 @@ 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
@@ -173,13 +177,11 @@ export default function BlockTools( { __unstableContentRef={ __unstableContentRef } /> ) } - { ! isZoomOutMode && - ( hasFixedToolbar || ! isLargeViewport ) && ( - - ) } + { /* 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 && ( ) } { /* Used for the inline rich text toolbar. */ } - + { ! isTopToolbar && ( + + ) } { children } { /* Used for inline rich text popovers. */ } { shouldShowContextualToolbar && ( .block-editor-block-toolbar { diff --git a/packages/block-editor/src/components/navigable-toolbar/index.js b/packages/block-editor/src/components/navigable-toolbar/index.js index e1204b90d0c5d..fe216e1058f6f 100644 --- a/packages/block-editor/src/components/navigable-toolbar/index.js +++ b/packages/block-editor/src/components/navigable-toolbar/index.js @@ -3,7 +3,6 @@ */ import { NavigableMenu, Toolbar } from '@wordpress/components'; import { - forwardRef, useState, useRef, useLayoutEffect, @@ -196,21 +195,16 @@ function useToolbarFocus( { }, [ focusEditorOnEscape, lastFocus, toolbarRef ] ); } -function UnforwardedNavigableToolbar( - { - children, - focusOnMount, - focusEditorOnEscape = false, - shouldUseKeyboardFocusShortcut = true, - __experimentalInitialIndex: initialIndex, - __experimentalOnIndexChange: onIndexChange, - ...props - }, - ref -) { - const maybeRef = useRef(); - // If a ref was not forwarded, we create one. - const toolbarRef = ref || maybeRef; +export default function NavigableToolbar( { + children, + focusOnMount, + focusEditorOnEscape = false, + shouldUseKeyboardFocusShortcut = true, + __experimentalInitialIndex: initialIndex, + __experimentalOnIndexChange: onIndexChange, + ...props +} ) { + const toolbarRef = useRef(); const isAccessibleToolbar = useIsAccessibleToolbar( toolbarRef ); useToolbarFocus( { @@ -246,7 +240,3 @@ function UnforwardedNavigableToolbar( ); } - -export const NavigableToolbar = forwardRef( UnforwardedNavigableToolbar ); - -export default NavigableToolbar; diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index fe16d791dc7c5..cf4e251874282 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -10,6 +10,7 @@ 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 } from './hooks/utils'; import BlockQuickNavigation from './components/block-quick-navigation'; @@ -41,6 +42,7 @@ lock( privateApis, { PrivateListView, ResizableBoxPopover, BlockInfo, + BlockContextualToolbar, useShouldContextualToolbarShow, cleanEmptyObject, BlockQuickNavigation, diff --git a/packages/customize-widgets/src/components/header/index.js b/packages/customize-widgets/src/components/header/index.js index 201831b90cd78..34e4573c719dd 100644 --- a/packages/customize-widgets/src/components/header/index.js +++ b/packages/customize-widgets/src/components/header/index.js @@ -6,11 +6,15 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { createPortal, useState, useEffect } from '@wordpress/element'; -import { __, _x, isRTL } from '@wordpress/i18n'; -import { ToolbarButton } from '@wordpress/components'; -import { NavigableToolbar } from '@wordpress/block-editor'; +import { Popover, ToolbarButton } from '@wordpress/components'; +import { useViewportMatch } from '@wordpress/compose'; +import { + NavigableToolbar, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; +import { createPortal, useEffect, useRef, 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'; /** @@ -18,6 +22,9 @@ 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, @@ -26,6 +33,8 @@ function Header( { setIsInserterOpened, isFixedToolbarActive, } ) { + const isLargeViewport = useViewportMatch( 'medium' ); + const blockToolbarRef = useRef(); const [ [ hasUndo, hasRedo ], setUndoRedo ] = useState( [ sidebar.hasUndo(), sidebar.hasRedo(), @@ -98,6 +107,18 @@ function Header( { , inserter.contentContainer[ 0 ] ) } + + { isFixedToolbarActive && isLargeViewport && ( + <> +
+ +
+ + + ) } ); } diff --git a/packages/customize-widgets/src/style.scss b/packages/customize-widgets/src/style.scss index bd6d16b89c7fa..3bf341c34c0eb 100644 --- a/packages/customize-widgets/src/style.scss +++ b/packages/customize-widgets/src/style.scss @@ -17,34 +17,3 @@ .customize-widgets-popover { @include reset; } - -/** - Fixed bloock toolbar overrides. We can't detect each editor instance - in the styles of the block editor component so we need to override - the fixed styles here because the breakpoint css does not fire in the - customizer's left panel. -*/ -.block-editor-block-contextual-toolbar { - &.is-fixed { - position: sticky; - top: 0; - left: 0; - z-index: z-index(".block-editor-block-list__insertion-point"); - width: calc(100% + 2 * 12px); //12px is the padding of customizer sidebar content - - overflow-y: hidden; - - border: none; - 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; - } - - &.is-collapsed { - margin-left: -12px; //12px is the padding of customizer sidebar content - } - } -} diff --git a/packages/edit-post/src/components/header/document-actions/index.js b/packages/edit-post/src/components/header/document-actions/index.js index 52df978e2cd5b..105b31e3122ac 100644 --- a/packages/edit-post/src/components/header/document-actions/index.js +++ b/packages/edit-post/src/components/header/document-actions/index.js @@ -20,21 +20,18 @@ import { displayShortcut } from '@wordpress/keycodes'; import { store as editPostStore } from '../../../store'; function DocumentActions() { - const { template, isEditing } = useSelect( ( select ) => { - const { isEditingTemplate, getEditedPostTemplate } = - select( editPostStore ); - const _isEditing = isEditingTemplate(); + const { template } = useSelect( ( select ) => { + const { getEditedPostTemplate } = select( editPostStore ); return { - template: _isEditing ? getEditedPostTemplate() : null, - isEditing: _isEditing, + template: getEditedPostTemplate(), }; }, [] ); const { clearSelectedBlock } = useDispatch( blockEditorStore ); const { setIsEditingTemplate } = useDispatch( editPostStore ); const { open: openCommandCenter } = useDispatch( commandsStore ); - if ( ! isEditing || ! template ) { + if ( ! template ) { return null; } diff --git a/packages/edit-post/src/components/header/header-toolbar/index.js b/packages/edit-post/src/components/header/header-toolbar/index.js index b86e66af7a849..9c650f8660da1 100644 --- a/packages/edit-post/src/components/header/header-toolbar/index.js +++ b/packages/edit-post/src/components/header/header-toolbar/index.js @@ -19,7 +19,6 @@ import { Button, ToolbarItem } from '@wordpress/components'; import { listView, plus } from '@wordpress/icons'; import { useRef, useCallback } from '@wordpress/element'; import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; -import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -33,7 +32,7 @@ const preventDefault = ( event ) => { event.preventDefault(); }; -function HeaderToolbar( { setListViewToggleElement } ) { +function HeaderToolbar( { hasFixedToolbar, setListViewToggleElement } ) { const inserterButton = useRef(); const { setIsInserterOpened, setIsListViewOpened } = useDispatch( editPostStore ); @@ -44,7 +43,6 @@ function HeaderToolbar( { setListViewToggleElement } ) { showIconLabels, isListViewOpen, listViewShortcut, - hasFixedToolbar, } = useSelect( ( select ) => { const { hasInserterItems, getBlockRootClientId, getBlockSelectionEnd } = select( blockEditorStore ); @@ -52,7 +50,6 @@ function HeaderToolbar( { setListViewToggleElement } ) { const { getEditorMode, isFeatureActive, isListViewOpened } = select( editPostStore ); const { getShortcutRepresentation } = select( keyboardShortcutsStore ); - const { get: getPreference } = select( preferencesStore ); return { // This setting (richEditingEnabled) should not live in the block editor's setting. @@ -69,7 +66,6 @@ function HeaderToolbar( { setListViewToggleElement } ) { listViewShortcut: getShortcutRepresentation( 'core/edit-post/toggle-list-view' ), - hasFixedToolbar: getPreference( 'core/edit-post', 'fixedToolbar' ), }; }, [] ); diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js index 2e0d470818fec..c1c8222394979 100644 --- a/packages/edit-post/src/components/header/index.js +++ b/packages/edit-post/src/components/header/index.js @@ -1,11 +1,28 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ +import { + privateApis as blockEditorPrivateApis, + store as blockEditorStore, +} from '@wordpress/block-editor'; import { PostSavedState, PostPreviewButton } from '@wordpress/editor'; +import { useEffect, useRef, useState } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { next, previous } from '@wordpress/icons'; import { PinnedItems } from '@wordpress/interface'; import { useViewportMatch } from '@wordpress/compose'; -import { __unstableMotion as motion } from '@wordpress/components'; +import { + Button, + __unstableMotion as motion, + Popover, +} from '@wordpress/components'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -19,6 +36,9 @@ import ViewLink from '../view-link'; import MainDashboardButton from './main-dashboard-button'; import { store as editPostStore } from '../../store'; import DocumentActions from './document-actions'; +import { unlock } from '../../lock-unlock'; + +const { BlockContextualToolbar } = unlock( blockEditorPrivateApis ); const slideY = { hidden: { y: '-50px' }, @@ -36,18 +56,43 @@ function Header( { setEntitiesSavedStatesCallback, setListViewToggleElement, } ) { - const isLargeViewport = useViewportMatch( 'large' ); - const { hasActiveMetaboxes, isPublishSidebarOpened, showIconLabels } = - useSelect( - ( select ) => ( { - hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(), - isPublishSidebarOpened: - select( editPostStore ).isPublishSidebarOpened(), - showIconLabels: - select( editPostStore ).isFeatureActive( 'showIconLabels' ), - } ), - [] - ); + const isWideViewport = useViewportMatch( 'large' ); + const isLargeViewport = useViewportMatch( 'medium' ); + const blockToolbarRef = useRef(); + const { + blockSelectionStart, + hasActiveMetaboxes, + hasFixedToolbar, + isEditingTemplate, + isPublishSidebarOpened, + showIconLabels, + } = useSelect( ( select ) => { + const { get: getPreference } = select( preferencesStore ); + + return { + blockSelectionStart: + select( blockEditorStore ).getBlockSelectionStart(), + hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(), + isEditingTemplate: select( editPostStore ).isEditingTemplate(), + isPublishSidebarOpened: + select( editPostStore ).isPublishSidebarOpened(), + hasFixedToolbar: getPreference( 'core/edit-post', 'fixedToolbar' ), + showIconLabels: + select( editPostStore ).isFeatureActive( 'showIconLabels' ), + }; + }, [] ); + + const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] = + useState( true ); + + const hasBlockSelected = !! blockSelectionStart; + + useEffect( () => { + // If we have a new block selection, show the block tools + if ( blockSelectionStart ) { + setIsBlockToolsCollapsed( false ); + } + }, [ blockSelectionStart ] ); return (
@@ -65,10 +110,52 @@ function Header( { className="edit-post-header__toolbar" > -
- + { hasFixedToolbar && isLargeViewport && ( + <> +
+ +
+ + { isEditingTemplate && hasBlockSelected && ( +