diff --git a/packages/edit-site/src/components/editor-canvas-container/index.js b/packages/edit-site/src/components/editor-canvas-container/index.js index baebc1bc1bc894..4f93c2e1995d29 100644 --- a/packages/edit-site/src/components/editor-canvas-container/index.js +++ b/packages/edit-site/src/components/editor-canvas-container/index.js @@ -9,7 +9,7 @@ import { import { ESCAPE } from '@wordpress/keycodes'; import { __ } from '@wordpress/i18n'; import { useDispatch, useSelect } from '@wordpress/data'; -import { closeSmall } from '@wordpress/icons'; +import { backup, closeSmall, seen } from '@wordpress/icons'; import { useFocusOnMount, useFocusReturn } from '@wordpress/compose'; import { store as preferencesStore } from '@wordpress/preferences'; import { @@ -30,17 +30,26 @@ const { EditorContentSlotFill, ResizableEditor } = unlock( editorPrivateApis ); * * @param {string} view Editor canvas container view. * - * @return {string} Translated string corresponding to value of view. Default is ''. + * @return {Object} Translated string for the view title and associated icon, both defaulting to ''. */ -function getEditorCanvasContainerTitle( view ) { +function getEditorCanvasContainerTitleAndIcon( view ) { switch ( view ) { case 'style-book': - return __( 'Style Book' ); + return { + title: __( 'Style Book' ), + icon: seen, + }; case 'global-styles-revisions': case 'global-styles-revisions:style-book': - return __( 'Style Revisions' ); + return { + title: __( 'Style Revisions' ), + icon: backup, + }; default: - return ''; + return { + title: '', + icon: '', + }; } } @@ -109,7 +118,9 @@ function EditorCanvasContainer( { return null; } - const title = getEditorCanvasContainerTitle( editorCanvasContainerView ); + const { title } = getEditorCanvasContainerTitleAndIcon( + editorCanvasContainerView + ); const shouldShowCloseButton = onClose || closeButtonLabel; return ( @@ -138,10 +149,11 @@ function EditorCanvasContainer( { ); } + function useHasEditorCanvasContainer() { const fills = useSlotFills( EditorContentSlotFill.privateKey ); return !! fills?.length; } export default EditorCanvasContainer; -export { useHasEditorCanvasContainer, getEditorCanvasContainerTitle }; +export { useHasEditorCanvasContainer, getEditorCanvasContainerTitleAndIcon }; diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 1b8f75b3c35e76..85a9a428fe2f2f 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -36,7 +36,7 @@ import PluginTemplateSettingPanel from '../plugin-template-setting-panel'; import GlobalStylesSidebar from '../global-styles-sidebar'; import { isPreviewingTheme } from '../../utils/is-previewing-theme'; import { - getEditorCanvasContainerTitle, + getEditorCanvasContainerTitleAndIcon, useHasEditorCanvasContainer, } from '../editor-canvas-container'; import SaveButton from '../save-button'; @@ -63,6 +63,7 @@ export default function EditSiteEditor( { isLoading } ) { currentPostIsTrashed, } = useSelect( ( select ) => { const { + getEditorCanvasContainerView, getEditedPostContext, getCanvasMode, isPage, @@ -84,9 +85,7 @@ export default function EditSiteEditor( { isLoading } ) { isEditingPage: isPage(), supportsGlobalStyles: getCurrentTheme()?.is_block_theme, showIconLabels: get( 'core', 'showIconLabels' ), - editorCanvasView: unlock( - select( editSiteStore ) - ).getEditorCanvasContainerView(), + editorCanvasView: getEditorCanvasContainerView(), currentPostIsTrashed: select( editorStore ).getCurrentPostAttribute( 'status' ) === 'trash', @@ -171,6 +170,10 @@ export default function EditSiteEditor( { isLoading } ) { [ history, createSuccessNotice ] ); + // Replace the title and icon displayed in the DocumentBar when there's an overlay visible. + const { title, icon } = + getEditorCanvasContainerTitleAndIcon( editorCanvasView ); + const isReady = ! isLoading; return ( @@ -197,11 +200,8 @@ export default function EditSiteEditor( { isLoading } ) { _isPreviewingTheme && } forceDisableBlockTools={ ! hasDefaultEditorCanvasView } - title={ - ! hasDefaultEditorCanvasView - ? getEditorCanvasContainerTitle( editorCanvasView ) - : undefined - } + title={ title } + icon={ icon } iframeProps={ iframeProps } onActionPerformed={ onActionPerformed } extraSidebarPanels={ diff --git a/packages/edit-site/src/hooks/commands/use-set-command-context.js b/packages/edit-site/src/hooks/commands/use-set-command-context.js index 2824a6cc99f1c3..30f7f7ce258c61 100644 --- a/packages/edit-site/src/hooks/commands/use-set-command-context.js +++ b/packages/edit-site/src/hooks/commands/use-set-command-context.js @@ -10,6 +10,7 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; */ import { store as editSiteStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import { useHasEditorCanvasContainer } from '../../components/editor-canvas-container'; const { useCommandContext } = unlock( commandsPrivateApis ); @@ -25,6 +26,9 @@ export default function useSetCommandContext() { hasBlockSelected: getBlockSelectionStart(), }; }, [] ); + + const hasEditorCanvasContainer = useHasEditorCanvasContainer(); + // Sets the right context for the command palette let commandContext = 'site-editor'; if ( canvasMode === 'edit' ) { @@ -33,5 +37,13 @@ export default function useSetCommandContext() { if ( hasBlockSelected ) { commandContext = 'block-selection-edit'; } + if ( hasEditorCanvasContainer ) { + /* + * The editor canvas overlay will likely be deprecated in the future, so for now we clear the command context + * to remove the suggested commands that may not make sense with Style Book or Style Revisions open. + * See https://github.com/WordPress/gutenberg/issues/62216. + */ + commandContext = ''; + } useCommandContext( commandContext ); } diff --git a/packages/editor/README.md b/packages/editor/README.md index a0769fc5bac966..8cfee5e3a7c113 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -262,6 +262,12 @@ _Usage_ ``` +_Parameters_ + +- _props_ `Object`: The component props. +- _props.title_ `string`: A title for the document, defaulting to the document or template title currently being edited. +- _props.icon_ `import("@wordpress/components").IconType`: An icon for the document, defaulting to an icon for document or template currently being edited. + _Returns_ - `JSX.Element`: The rendered DocumentBar component. diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 82603bb1c71935..34cb68de785157 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -52,10 +52,15 @@ const MotionButton = motion( Button ); * ```jsx * * ``` + * @param {Object} props The component props. + * @param {string} props.title A title for the document, defaulting to the document or + * template title currently being edited. + * @param {import("@wordpress/components").IconType} props.icon An icon for the document, defaulting to an icon for document + * or template currently being edited. * * @return {JSX.Element} The rendered DocumentBar component. */ -export default function DocumentBar() { +export default function DocumentBar( props ) { const { postType, documentTitle, @@ -111,7 +116,9 @@ export default function DocumentBar() { const isTemplate = TEMPLATE_POST_TYPES.includes( postType ); const isGlobalEntity = GLOBAL_POST_TYPES.includes( postType ); const hasBackButton = !! onNavigateToPreviousEntityRecord; - const title = isTemplate ? templateTitle : documentTitle; + const entityTitle = isTemplate ? templateTitle : documentTitle; + const title = props.title || entityTitle; + const icon = props.icon || templateIcon; const mounted = useRef( false ); useEffect( () => { @@ -180,12 +187,12 @@ export default function DocumentBar() { isReducedMotion ? { duration: 0 } : undefined } > - + ) } diff --git a/packages/editor/src/components/header/index.js b/packages/editor/src/components/header/index.js index 14b62def0cfa74..4cf28748b2d7a2 100644 --- a/packages/editor/src/components/header/index.js +++ b/packages/editor/src/components/header/index.js @@ -51,6 +51,7 @@ function Header( { forceDisableBlockTools, setEntitiesSavedStatesCallback, title, + icon, } ) { const isWideViewport = useViewportMatch( 'large' ); const isLargeViewport = useViewportMatch( 'medium' ); @@ -116,7 +117,7 @@ function Header( { ! isBlockToolsCollapsed && hasTopToolbar, } ) } > - { ! title ? : title } + { 'style book should be visible' ).toBeVisible(); } ); + + test( 'should allow opening the command menu from the header when open', async ( { + page, + } ) => { + // Open the command menu from the header. + await page + .getByRole( 'heading', { + name: 'Style Book', + } ) + .click(); + + await expect( + page.getByLabel( 'Search commands and settings' ) + ).toBeVisible(); + } ); } ); class StyleBook { diff --git a/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js b/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js index 9eb98e55005c70..f48c819c3a0891 100644 --- a/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js +++ b/test/e2e/specs/site-editor/user-global-styles-revisions.spec.js @@ -155,11 +155,14 @@ test.describe( 'Style Revisions', () => { } ) => { await editor.canvas.locator( 'body' ).click(); await userGlobalStylesRevisions.openStylesPanel(); + // Search for exact names to avoid selecting the command bar button in the header. const revisionsButton = page.getByRole( 'button', { name: 'Revisions', + exact: true, } ); const styleBookButton = page.getByRole( 'button', { name: 'Style Book', + exact: true, } ); await revisionsButton.click(); // We can see the Revisions list. @@ -224,6 +227,32 @@ test.describe( 'Style Revisions', () => { ).toBeVisible(); } ); + test( 'should allow opening the command menu from the header when open', async ( { + page, + editor, + userGlobalStylesRevisions, + } ) => { + await editor.canvas.locator( 'body' ).click(); + await userGlobalStylesRevisions.openStylesPanel(); + await page + .getByRole( 'button', { + name: 'Revisions', + exact: true, + } ) + .click(); + + // Open the command menu from the header. + await page + .getByRole( 'heading', { + name: 'Style Revisions', + } ) + .click(); + + await expect( + page.getByLabel( 'Search commands and settings' ) + ).toBeVisible(); + } ); + test( 'should paginate', async ( { page, editor,