-
+
+
{ ( isWideViewport || ! showIconLabels ) && (
<>
{ isLargeViewport && (
@@ -152,6 +96,7 @@ function HeaderToolbar() {
variant={ showIconLabels ? 'tertiary' : undefined }
/>
{ overflowItems }
+ { hasSelectedBlocks && }
>
) }
diff --git a/packages/edit-post/src/components/header/header-toolbar/style.scss b/packages/edit-post/src/components/header/header-toolbar/style.scss
index 87aec00004c02b..bab6317357d2c2 100644
--- a/packages/edit-post/src/components/header/header-toolbar/style.scss
+++ b/packages/edit-post/src/components/header/header-toolbar/style.scss
@@ -1,11 +1,11 @@
-.edit-post-header-toolbar {
+.edit-post-header-document-toolbar {
display: inline-flex;
flex-grow: 1;
align-items: center;
border: none;
// Hide all action buttons except the inserter on mobile.
- .edit-post-header-toolbar__left > .components-button {
+ .edit-post-header-document-toolbar__left > .components-button {
display: none;
@include break-small() {
@@ -13,7 +13,7 @@
}
}
- .edit-post-header-toolbar__left > .edit-post-header-toolbar__inserter-toggle {
+ .edit-post-header-document-toolbar__left > .edit-post-header-toolbar__inserter-toggle {
display: inline-flex;
svg {
@@ -39,11 +39,92 @@
// The Toolbar component adds different styles to buttons, so we reset them
// here to the original button styles
- .edit-post-header-toolbar__left > .components-button.has-icon,
- .edit-post-header-toolbar__left > .components-dropdown > .components-button.has-icon {
+ .edit-post-header-document-toolbar__left > .components-button.has-icon:first-child {
+ margin-right: $grid-unit-10;
+ }
+
+ .edit-post-header-document-toolbar__left > .components-button.has-icon,
+ .edit-post-header-document-toolbar__left > .components-dropdown > .components-button.has-icon {
+ height: $grid-unit-40;
+ min-width: $grid-unit-40;
+ margin-right: $grid-unit-05;
+ padding: 0;
+ width: 32px;
+
+ &.is-pressed {
+ background: $gray-900;
+ }
+
+ &:focus:not(:disabled) {
+ box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color), inset 0 0 0 $border-width $white;
+ outline: 1px solid transparent;
+ }
+
+ &::before {
+ display: none;
+ }
+ }
+
+ & > .edit-post-header-document-toolbar__left button.components-button.edit-post-header-toolbar__block-tools-toggle.is-primary.has-icon {
+ height: $button-size;
+ min-width: $button-size;
+ background-color: #fff;
+ color: #000;
+ margin-left: $grid-unit-10;
+ border-left: 1px solid #ddd;
+ padding-left: $grid-unit-15;
+
+ &:hover {
+ color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba));
+ }
+ }
+}
+
+.edit-post-header-block-toolbar {
+ display: inline-flex;
+ flex-grow: 1;
+ align-items: center;
+ border: none;
+ padding-left: 24px; //compensates for the edit-post-header-document-toolbar__left left padding
+ height: 32px;
+ overflow: hidden; //limits the height of the separators
+
+ > .edit-post-header-toolbar__inserter-toggle {
+ display: inline-flex;
+
+ svg {
+ transition: transform cubic-bezier(0.165, 0.84, 0.44, 1) 0.2s;
+ @include reduce-motion("transition");
+ }
+
+ &.is-pressed {
+ svg {
+ transform: rotate(45deg);
+ }
+ }
+ }
+
+ & > button.components-button.edit-post-header-toolbar__document-tools-toggle.is-primary.has-icon {
height: $button-size;
min-width: $button-size;
padding: 6px;
+ background-color: #fff;
+ color: #000;
+ border-right: 1px solid #ddd;
+
+ &:hover {
+ color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba));
+ }
+ }
+
+ // The Toolbar component adds different styles to buttons, so we reset them
+ // here to the original button styles
+ & > button.components-button.edit-post-header-toolbar__inserter-toggle.is-primary.has-icon {
+ height: 32px;
+ margin-right: 8px;
+ min-width: 32px;
+ padding: 0;
+ width: 32px;
&.is-pressed {
background: $gray-900;
@@ -57,28 +138,35 @@
&::before {
display: none;
}
+
+ .show-icon-labels & {
+ width: auto;
+ height: 36px;
+ padding: 0 $grid-unit-10;
+ }
}
+
}
// Reduced UI.
.edit-post-header.has-reduced-ui {
@include break-small () {
// Apply transition to every button but the first one.
- .edit-post-header-toolbar__left > * + .components-button,
- .edit-post-header-toolbar__left > * + .components-dropdown > [aria-expanded="false"] {
+ .edit-post-header-document-toolbar__left > * + .components-button,
+ .edit-post-header-document-toolbar__left > * + .components-dropdown > [aria-expanded="false"] {
transition: opacity 0.1s linear;
@include reduce-motion("transition");
}
// Zero out opacity unless hovered.
- &:not(:hover) .edit-post-header-toolbar__left > * + .components-button,
- &:not(:hover) .edit-post-header-toolbar__left > * + .components-dropdown > [aria-expanded="false"] {
+ &:not(:hover) .edit-post-header-document-toolbar__left > * + .components-button,
+ &:not(:hover) .edit-post-header-document-toolbar__left > * + .components-dropdown > [aria-expanded="false"] {
opacity: 0;
}
}
}
-.edit-post-header-toolbar__left {
+.edit-post-header-document-toolbar__left {
display: inline-flex;
align-items: center;
padding-left: $grid-unit-10;
@@ -92,7 +180,7 @@
}
}
-.edit-post-header-toolbar .edit-post-header-toolbar__left > .edit-post-header-toolbar__inserter-toggle.has-icon {
+.edit-post-header-document-toolbar .edit-post-header-document-toolbar__left > .edit-post-header-document-toolbar__inserter-toggle.has-icon {
margin-right: $grid-unit-10;
// Special dimensions for this button.
min-width: 32px;
@@ -107,6 +195,6 @@
}
}
-.show-icon-labels .edit-post-header-toolbar__left > * + * {
+.show-icon-labels .edit-post-header-document-toolbar__left > * + * {
margin-left: $grid-unit-10;
}
diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js
index a7bdccbfe44d9d..0c877b1b4b0a28 100644
--- a/packages/edit-post/src/components/header/index.js
+++ b/packages/edit-post/src/components/header/index.js
@@ -1,11 +1,25 @@
/**
* WordPress dependencies
*/
+import { __ } from '@wordpress/i18n';
import { PostSavedState, PostPreviewButton } from '@wordpress/editor';
+import { useEffect, useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { PinnedItems } from '@wordpress/interface';
import { useViewportMatch } from '@wordpress/compose';
-import { __unstableMotion as motion } from '@wordpress/components';
+import {
+ __unstableMotion as motion,
+ Button,
+ ToolbarItem,
+} from '@wordpress/components';
+import {
+ BlockIcon,
+ NavigableToolbar,
+ store as blockEditorStore,
+ BlockToolbar,
+ useBlockDisplayInformation,
+} from '@wordpress/block-editor';
+import { levelUp } from '@wordpress/icons';
/**
* Internal dependencies
@@ -18,17 +32,64 @@ import { default as DevicePreview } from '../device-preview';
import MainDashboardButton from './main-dashboard-button';
import { store as editPostStore } from '../../store';
import TemplateTitle from './template-title';
+import InserterButton from './inserter-button';
+
+function MaybeHide( { children, isHidden } ) {
+ if ( isHidden ) {
+ return
{ children }
;
+ }
+ return children;
+}
+
+function ShowDocumentToolbarButton( { onClick } ) {
+ return (
+
+ );
+}
+
+function ShowBlockToolbarButton( { onClick, icon } ) {
+ return (
+
}
+ onClick={ onClick }
+ />
+ );
+}
function Header( { setEntitiesSavedStatesCallback } ) {
const isLargeViewport = useViewportMatch( 'large' );
+ const isMobileViewPort = useViewportMatch( 'medium', '<' );
+ const isDesktopViewport = useViewportMatch( 'medium', '>=' );
const {
hasActiveMetaboxes,
isPublishSidebarOpened,
isSaving,
+ hasFixedToolbar,
+ hasSelectedBlocks,
showIconLabels,
isDistractionFreeMode,
- } = useSelect(
- ( select ) => ( {
+ isNavigationMode,
+ selectedBlockClientId,
+ } = useSelect( ( select ) => {
+ const {
+ getSettings,
+ getSelectedBlockClientIds,
+ getSelectedBlockClientId,
+ isNavigationMode: _isNavigationMode,
+ } = select( blockEditorStore );
+ const settings = getSettings();
+ const _selectedBlockClientIds = getSelectedBlockClientIds();
+ return {
+ hasSelectedBlocks: !! _selectedBlockClientIds.length,
hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(),
isPublishSidebarOpened:
select( editPostStore ).isPublishSidebarOpened(),
@@ -37,12 +98,30 @@ function Header( { setEntitiesSavedStatesCallback } ) {
select( editPostStore ).isFeatureActive( 'showIconLabels' ),
isDistractionFreeMode:
select( editPostStore ).isFeatureActive( 'distractionFree' ),
- } ),
- []
- );
+ hasFixedToolbar: settings.hasFixedToolbar,
+ isNavigationMode: _isNavigationMode(),
+ selectedBlockClientId: getSelectedBlockClientId(),
+ };
+ } );
const isDistractionFree = isDistractionFreeMode && isLargeViewport;
+ const [ headerToolbar, setHeaderToolbar ] = useState( 'document' );
+
+ const blockInformation = useBlockDisplayInformation(
+ selectedBlockClientId
+ );
+
+ useEffect( () => {
+ if ( isNavigationMode ) {
+ setHeaderToolbar( 'document' );
+ } else if ( hasSelectedBlocks ) {
+ setHeaderToolbar( 'block' );
+ } else {
+ setHeaderToolbar( 'document' );
+ }
+ }, [ hasSelectedBlocks, isNavigationMode ] );
+
const slideY = {
hidden: isDistractionFree ? { y: '-50' } : { y: 0 },
hover: { y: 0, transition: { type: 'tween', delay: 0.2 } },
@@ -53,6 +132,8 @@ function Header( { setEntitiesSavedStatesCallback } ) {
hover: { x: 0, transition: { type: 'tween', delay: 0.2 } },
};
+ const blockToolbarAriaLabel = __( 'Block tools' );
+
return (
@@ -68,7 +149,45 @@ function Header( { setEntitiesSavedStatesCallback } ) {
transition={ { type: 'tween', delay: 0.8 } }
className="edit-post-header__toolbar"
>
-
+ { ( ! hasFixedToolbar ||
+ isNavigationMode ||
+ isMobileViewPort ) && }
+ { hasFixedToolbar &&
+ ! isNavigationMode &&
+ isDesktopViewport && (
+ <>
+
+ (
+
+ setHeaderToolbar( 'block' )
+ }
+ icon={ blockInformation.icon }
+ />
+ ) }
+ />
+
+ { hasSelectedBlocks &&
+ headerToolbar === 'block' && (
+
+
+
+ setHeaderToolbar( 'document' )
+ }
+ />
+
+
+ ) }
+ >
+ ) }
{
+ event.preventDefault();
+};
+
+export default function InserterButton() {
+ const inserterButton = useRef();
+ const { setIsInserterOpened } = useDispatch( editPostStore );
+ const { isInserterEnabled, isInserterOpened, showIconLabels } = useSelect(
+ ( select ) => {
+ const {
+ hasInserterItems,
+ getBlockRootClientId,
+ getBlockSelectionEnd,
+ } = select( blockEditorStore );
+ const { getEditorSettings } = select( editorStore );
+ const { getEditorMode, isFeatureActive } = select( editPostStore );
+
+ return {
+ // This setting (richEditingEnabled) should not live in the block editor's setting.
+ isInserterEnabled:
+ getEditorMode() === 'visual' &&
+ getEditorSettings().richEditingEnabled &&
+ hasInserterItems(
+ getBlockRootClientId( getBlockSelectionEnd() )
+ ),
+ isInserterOpened: select( editPostStore ).isInserterOpened(),
+ showIconLabels: isFeatureActive( 'showIconLabels' ),
+ };
+ },
+ []
+ );
+
+ const toggleInserter = useCallback( () => {
+ if ( isInserterOpened ) {
+ // Focusing the inserter button should close the inserter popover.
+ // However, there are some cases it won't close when the focus is lost.
+ // See https://github.com/WordPress/gutenberg/issues/43090 for more details.
+ inserterButton.current.focus();
+ setIsInserterOpened( false );
+ } else {
+ setIsInserterOpened( true );
+ }
+ }, [ isInserterOpened, setIsInserterOpened ] );
+
+ /* translators: button label text should, if possible, be under 16 characters. */
+ const longLabel = _x(
+ 'Toggle block inserter',
+ 'Generic label for block inserter button'
+ );
+ const shortLabel = ! isInserterOpened ? __( 'Add' ) : __( 'Close' );
+
+ return (
+
+ );
+}
diff --git a/packages/edit-post/src/components/header/style.scss b/packages/edit-post/src/components/header/style.scss
index 160543684a702e..70a0a845e59a47 100644
--- a/packages/edit-post/src/components/header/style.scss
+++ b/packages/edit-post/src/components/header/style.scss
@@ -238,3 +238,23 @@
z-index: 35;
}
}
+
+.maybeHide {
+ position: fixed;
+ top: -9999px;
+}
+
+.maybeHide:focus-within {
+ position: relative;
+ top: 0;
+}
+
+.maybeHide:focus-within > .edit-post-header-document-toolbar .edit-post-header-document-toolbar__left > .components-button.edit-post-header-toolbar__block-tools-toggle,
+.maybeHide:focus-within + .edit-post-header-block-toolbar > .edit-post-header-toolbar__document-tools-toggle,
+.maybeHide:focus-within + .edit-post-header-block-toolbar > .edit-post-header-toolbar__inserter-toggle {
+ display: none;
+}
+
+.maybeHide:focus-within + .edit-post-header-block-toolbar {
+ padding-left: 0;
+}
diff --git a/packages/edit-post/src/components/header/writing-menu/index.js b/packages/edit-post/src/components/header/writing-menu/index.js
index 6cea56392381e1..ac21030cc9cd69 100644
--- a/packages/edit-post/src/components/header/writing-menu/index.js
+++ b/packages/edit-post/src/components/header/writing-menu/index.js
@@ -6,10 +6,7 @@ import { MenuGroup } from '@wordpress/components';
import { __, _x } from '@wordpress/i18n';
import { useViewportMatch } from '@wordpress/compose';
import { displayShortcut } from '@wordpress/keycodes';
-import {
- PreferenceToggleMenuItem,
- store as preferencesStore,
-} from '@wordpress/preferences';
+import { PreferenceToggleMenuItem } from '@wordpress/preferences';
import { store as blockEditorStore } from '@wordpress/block-editor';
/**
@@ -32,13 +29,11 @@ function WritingMenu() {
const { setIsInserterOpened, setIsListViewOpened, closeGeneralSidebar } =
useDispatch( postEditorStore );
- const { set: setPreference } = useDispatch( preferencesStore );
const { selectBlock } = useDispatch( blockEditorStore );
const toggleDistractionFree = () => {
registry.batch( () => {
- setPreference( 'core/edit-post', 'fixedToolbar', false );
setIsInserterOpened( false );
setIsListViewOpened( false );
closeGeneralSidebar();
diff --git a/packages/edit-post/src/components/keyboard-shortcuts/index.js b/packages/edit-post/src/components/keyboard-shortcuts/index.js
index 13a989de7fd076..c330c7aac250d5 100644
--- a/packages/edit-post/src/components/keyboard-shortcuts/index.js
+++ b/packages/edit-post/src/components/keyboard-shortcuts/index.js
@@ -11,7 +11,6 @@ import { __ } from '@wordpress/i18n';
import { store as editorStore } from '@wordpress/editor';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { store as noticesStore } from '@wordpress/notices';
-import { store as preferencesStore } from '@wordpress/preferences';
import { createBlock } from '@wordpress/blocks';
/**
@@ -45,10 +44,7 @@ function KeyboardShortcuts() {
} = useDispatch( editPostStore );
const { registerShortcut } = useDispatch( keyboardShortcutsStore );
- const { set: setPreference } = useDispatch( preferencesStore );
-
const toggleDistractionFree = () => {
- setPreference( 'core/edit-post', 'fixedToolbar', false );
setIsInserterOpened( false );
setIsListViewOpened( false );
closeGeneralSidebar();
diff --git a/packages/edit-post/src/components/preferences-modal/index.js b/packages/edit-post/src/components/preferences-modal/index.js
index 77c6383b13f32c..41aaa123560423 100644
--- a/packages/edit-post/src/components/preferences-modal/index.js
+++ b/packages/edit-post/src/components/preferences-modal/index.js
@@ -19,7 +19,6 @@ import {
PreferencesModalTabs,
PreferencesModalSection,
} from '@wordpress/interface';
-import { store as preferencesStore } from '@wordpress/preferences';
/**
* Internal dependencies
@@ -65,10 +64,7 @@ export default function EditPostPreferencesModal() {
const { closeGeneralSidebar, setIsListViewOpened, setIsInserterOpened } =
useDispatch( editPostStore );
- const { set: setPreference } = useDispatch( preferencesStore );
-
const toggleDistractionFree = () => {
- setPreference( 'core/edit-post', 'fixedToolbar', false );
setIsInserterOpened( false );
setIsListViewOpened( false );
closeGeneralSidebar();
diff --git a/packages/edit-site/src/components/header-edit-mode/index.js b/packages/edit-site/src/components/header-edit-mode/index.js
index 448682100092d6..4e08c3fa22ae25 100644
--- a/packages/edit-site/src/components/header-edit-mode/index.js
+++ b/packages/edit-site/src/components/header-edit-mode/index.js
@@ -6,19 +6,28 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
-import { useCallback, useRef } from '@wordpress/element';
+import { useEffect, useState, useCallback, useRef } from '@wordpress/element';
import { useViewportMatch } from '@wordpress/compose';
import { store as coreStore } from '@wordpress/core-data';
import {
+ BlockIcon,
+ BlockToolbar,
ToolSelector,
__experimentalPreviewOptions as PreviewOptions,
NavigableToolbar,
store as blockEditorStore,
+ useBlockDisplayInformation,
} from '@wordpress/block-editor';
import { useSelect, useDispatch } from '@wordpress/data';
import { PinnedItems } from '@wordpress/interface';
import { _x, __ } from '@wordpress/i18n';
-import { listView, plus, external, chevronUpDown } from '@wordpress/icons';
+import {
+ listView,
+ plus,
+ external,
+ chevronUpDown,
+ levelUp,
+} from '@wordpress/icons';
import {
Button,
ToolbarItem,
@@ -39,11 +48,43 @@ import RedoButton from './undo-redo/redo';
import DocumentActions from './document-actions';
import { store as editSiteStore } from '../../store';
import { useHasStyleBook } from '../style-book';
+import InserterButton from './inserter-button';
const preventDefault = ( event ) => {
event.preventDefault();
};
+function MaybeHide( { children, isHidden } ) {
+ if ( isHidden ) {
+ return { children }
;
+ }
+ return children;
+}
+
+function ShowDocumentToolbarButton( { onClick } ) {
+ return (
+
+ );
+}
+
+function ShowBlockToolbarButton( { onClick, icon } ) {
+ return (
+ }
+ onClick={ onClick }
+ />
+ );
+}
+
export default function HeaderEditMode() {
const inserterButton = useRef();
const {
@@ -91,6 +132,32 @@ export default function HeaderEditMode() {
};
}, [] );
+ const isMobileViewPort = useViewportMatch( 'medium', '<' );
+ const isDesktopViewport = useViewportMatch( 'medium', '>=' );
+ const {
+ hasFixedToolbar,
+ hasSelectedBlocks,
+ isNavigationMode,
+ selectedBlockClientId,
+ } = useSelect( ( select ) => {
+ const {
+ getSettings,
+ getSelectedBlockClientIds,
+ getSelectedBlockClientId,
+ isNavigationMode: _isNavigationMode,
+ } = select( blockEditorStore );
+ const settings = getSettings();
+ const _selectedBlockClientIds = getSelectedBlockClientIds();
+ return {
+ hasSelectedBlocks: !! _selectedBlockClientIds.length,
+ hasFixedToolbar: settings.hasFixedToolbar,
+ isNavigationMode: _isNavigationMode(),
+ selectedBlockClientId: getSelectedBlockClientId(),
+ };
+ } );
+
+ const [ headerToolbar, setHeaderToolbar ] = useState( 'document' );
+
const {
__experimentalSetPreviewDeviceType: setPreviewDeviceType,
setIsInserterOpened,
@@ -132,100 +199,154 @@ export default function HeaderEditMode() {
window?.__experimentalEnableZoomedOutView && isVisualMode;
const isZoomedOutView = blockEditorMode === 'zoom-out';
+ const blockToolbarAriaLabel = __( 'Block tools' );
+
+ const blockInformation = useBlockDisplayInformation(
+ selectedBlockClientId
+ );
+
+ useEffect( () => {
+ if ( isNavigationMode ) {
+ setHeaderToolbar( 'document' );
+ } else if ( hasSelectedBlocks ) {
+ setHeaderToolbar( 'block' );
+ } else {
+ setHeaderToolbar( 'document' );
+ }
+ }, [ hasSelectedBlocks, isNavigationMode ] );
+
+ const HeaderToolbar = ( { BlockToolbarToggle, areSelectedBlocks } ) => {
+ return (
+
+
+
+ { isLargeViewport && (
+ <>
+
+
+
+
+ { isZoomedOutViewExperimentEnabled && (
+ {
+ setPreviewDeviceType( 'desktop' );
+ __unstableSetEditorMode(
+ isZoomedOutView
+ ? 'edit'
+ : 'zoom-out'
+ );
+ } }
+ />
+ ) }
+ { areSelectedBlocks && }
+ >
+ ) }
+
+
+ );
+ };
+
return (
- { ! hasStyleBook && (
-
-
-
- { isLargeViewport && (
- <>
-
-
- }
+ { hasFixedToolbar &&
+ ! hasStyleBook &&
+ ! isNavigationMode &&
+ isDesktopViewport && (
+ <>
+
+ (
+
+ setHeaderToolbar( 'block' )
+ }
+ icon={ blockInformation.icon }
+ />
+ ) }
+ />
+
+ { hasSelectedBlocks && headerToolbar === 'block' && (
+
+
+
+ setHeaderToolbar( 'document' )
}
/>
-
- { isZoomedOutViewExperimentEnabled && (
- {
- setPreviewDeviceType( 'desktop' );
- __unstableSetEditorMode(
- isZoomedOutView
- ? 'edit'
- : 'zoom-out'
- );
- } }
- />
- ) }
- >
+
) }
-
-
- ) }
-
+ >
+ ) }
{ hasStyleBook ? __( 'Style Book' ) : }
-
{ ! isFocusMode && ! hasStyleBook && (
diff --git a/packages/edit-site/src/components/header-edit-mode/inserter-button/index.js b/packages/edit-site/src/components/header-edit-mode/inserter-button/index.js
new file mode 100644
index 00000000000000..55efd5faa9a456
--- /dev/null
+++ b/packages/edit-site/src/components/header-edit-mode/inserter-button/index.js
@@ -0,0 +1,85 @@
+/**
+ * WordPress dependencies
+ */
+import { useRef, useCallback } from '@wordpress/element';
+import { __, _x } from '@wordpress/i18n';
+/**
+ * WordPress dependencies
+ */
+import { Button, ToolbarItem } from '@wordpress/components';
+import { plus } from '@wordpress/icons';
+import { useSelect, useDispatch } from '@wordpress/data';
+import { store as blockEditorStore } from '@wordpress/block-editor';
+import { store as editorStore } from '@wordpress/editor';
+/**
+ * Internal dependencies
+ */
+import { store as editPostStore } from '../../../store';
+
+const preventDefault = ( event ) => {
+ event.preventDefault();
+};
+
+export default function InserterButton() {
+ const inserterButton = useRef();
+ const { setIsInserterOpened } = useDispatch( editPostStore );
+ const { isInserterEnabled, isInserterOpened, showIconLabels } = useSelect(
+ ( select ) => {
+ const {
+ hasInserterItems,
+ getBlockRootClientId,
+ getBlockSelectionEnd,
+ } = select( blockEditorStore );
+ const { getEditorSettings } = select( editorStore );
+ const { getEditorMode, isFeatureActive } = select( editPostStore );
+
+ return {
+ // This setting (richEditingEnabled) should not live in the block editor's setting.
+ isInserterEnabled:
+ getEditorMode() === 'visual' &&
+ getEditorSettings().richEditingEnabled &&
+ hasInserterItems(
+ getBlockRootClientId( getBlockSelectionEnd() )
+ ),
+ isInserterOpened: select( editPostStore ).isInserterOpened(),
+ showIconLabels: isFeatureActive( 'showIconLabels' ),
+ };
+ },
+ []
+ );
+
+ const toggleInserter = useCallback( () => {
+ if ( isInserterOpened ) {
+ // Focusing the inserter button should close the inserter popover.
+ // However, there are some cases it won't close when the focus is lost.
+ // See https://github.com/WordPress/gutenberg/issues/43090 for more details.
+ inserterButton.current.focus();
+ setIsInserterOpened( false );
+ } else {
+ setIsInserterOpened( true );
+ }
+ }, [ isInserterOpened, setIsInserterOpened ] );
+
+ /* translators: button label text should, if possible, be under 16 characters. */
+ const longLabel = _x(
+ 'Toggle block inserter',
+ 'Generic label for block inserter button'
+ );
+ const shortLabel = ! isInserterOpened ? __( 'Add' ) : __( 'Close' );
+
+ return (
+
+ );
+}
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 d26bad43e356da..2387c6dca59abb 100644
--- a/packages/edit-site/src/components/header-edit-mode/style.scss
+++ b/packages/edit-site/src/components/header-edit-mode/style.scss
@@ -67,6 +67,19 @@ $header-toolbar-min-width: 335px;
}
}
}
+
+ & > button.components-button.edit-site-header-toolbar__block-tools-toggle.is-primary.has-icon {
+ height: $button-size;
+ min-width: $button-size;
+ padding: 6px;
+ background-color: #fff;
+ color: #000;
+ border-left: 1px solid #ddd;
+
+ &:hover {
+ color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba));
+ }
+ }
}
/**
@@ -195,3 +208,91 @@ $header-toolbar-min-width: 335px;
margin-left: $grid-unit-10;
}
}
+
+.edit-site-header-block-toolbar {
+ display: inline-flex;
+ flex-grow: 1;
+ align-items: center;
+ border: none;
+ padding-left: 24px; //compensates for the edit-post-header-document-toolbar__left left padding
+ height: 32px;
+ overflow: hidden; //limits the height of the separators
+
+ > .edit-site-header-edit-mode__inserter-toggle {
+ display: inline-flex;
+
+ svg {
+ transition: transform cubic-bezier(0.165, 0.84, 0.44, 1) 0.2s;
+ @include reduce-motion("transition");
+ }
+
+ &.is-pressed {
+ svg {
+ transform: rotate(45deg);
+ }
+ }
+ }
+
+ & > button.components-button.edit-site-header-toolbar__document-tools-toggle.is-primary.has-icon {
+ height: $button-size;
+ min-width: $button-size;
+ padding: 6px;
+ background-color: #fff;
+ color: #000;
+ border-right: 1px solid #ddd;
+
+ &:hover {
+ color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba));
+ }
+ }
+
+ // The Toolbar component adds different styles to buttons, so we reset them
+ // here to the original button styles
+ & > button.components-button.edit-site-header-edit-mode__inserter-toggle.is-primary.has-icon {
+ height: 32px;
+ margin-right: 8px;
+ min-width: 32px;
+ padding: 0;
+ width: 32px;
+
+ &.is-pressed {
+ background: $gray-900;
+ }
+
+ &:focus:not(:disabled) {
+ box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color), inset 0 0 0 $border-width $white;
+ outline: 1px solid transparent;
+ }
+
+ &::before {
+ display: none;
+ }
+
+ .show-icon-labels & {
+ width: auto;
+ height: 36px;
+ padding: 0 $grid-unit-10;
+ }
+ }
+
+}
+
+.maybeHide {
+ position: fixed;
+ top: -9999px;
+}
+
+.maybeHide:focus-within {
+ position: relative;
+ top: 0;
+}
+
+.maybeHide:focus-within > .edit-site-header-document-toolbar .edit-site-header-edit-mode__start > .components-button.edit-site-header-toolbar__block-tools-toggle,
+.maybeHide:focus-within + .edit-site-header-block-toolbar > .edit-site-header-toolbar__document-tools-toggle,
+.maybeHide:focus-within + .edit-site-header-block-toolbar > .edit-site-header-edit-mode__inserter-toggle {
+ display: none;
+}
+
+.maybeHide:focus-within + .edit-site-header-block-toolbar {
+ padding-left: 0;
+}
diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js
index 45ead66387db7f..7c4be01f3fb951 100644
--- a/packages/icons/src/index.js
+++ b/packages/icons/src/index.js
@@ -119,6 +119,7 @@ export { default as key } from './library/key';
export { default as keyboardClose } from './library/keyboard-close';
export { default as keyboardReturn } from './library/keyboard-return';
export { default as layout } from './library/layout';
+export { default as levelUp } from './library/level-up';
export { default as lifesaver } from './library/lifesaver';
export { default as lineDashed } from './library/line-dashed';
export { default as lineDotted } from './library/line-dotted';
diff --git a/packages/icons/src/library/level-up.js b/packages/icons/src/library/level-up.js
new file mode 100644
index 00000000000000..fc992c8dbada56
--- /dev/null
+++ b/packages/icons/src/library/level-up.js
@@ -0,0 +1,12 @@
+/**
+ * WordPress dependencies
+ */
+import { SVG, Path } from '@wordpress/primitives';
+
+const levelUp = (
+
+);
+
+export default levelUp;