diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss
index 0e3dddf70632b..c8c35acfce486 100644
--- a/packages/base-styles/_z-index.scss
+++ b/packages/base-styles/_z-index.scss
@@ -189,8 +189,6 @@ $z-layers: (
".customize-widgets__block-toolbar": 7,
// Site editor layout
- ".edit-site-layout__header-container": 4,
- ".edit-site-layout__hub": 3,
".edit-site-page-header": 2,
".edit-site-page-content": 1,
".edit-site-patterns__dataviews-list-pagination": 2,
diff --git a/packages/edit-site/src/components/block-editor/style.scss b/packages/edit-site/src/components/block-editor/style.scss
index 3849eed24a4ea..2e6e7f95b715f 100644
--- a/packages/edit-site/src/components/block-editor/style.scss
+++ b/packages/edit-site/src/components/block-editor/style.scss
@@ -1,4 +1,15 @@
+/* stylelint-disable -- Disable reason: View Transitions not supported properly by stylelint. */
+::view-transition-old(frame),
+::view-transition-new(frame) {
+ animation-duration: 0;
+}
+/* stylelint-enable */
+
.edit-site-visual-editor__editor-canvas {
+ /* stylelint-disable -- Disable reason: View Transitions not supported properly by stylelint. */
+ view-transition-name: frame;
+ /* stylelint-enable */
+
&.is-focused {
outline: calc(2 * var(--wp-admin-border-width-focus)) solid var(--wp-admin-theme-color);
outline-offset: calc(-2 * var(--wp-admin-border-width-focus));
diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js
index 779b69cdeeef2..cd6b719875239 100644
--- a/packages/edit-site/src/components/editor/index.js
+++ b/packages/edit-site/src/components/editor/index.js
@@ -7,6 +7,7 @@ import clsx from 'clsx';
* WordPress dependencies
*/
import { useDispatch, useSelect } from '@wordpress/data';
+import { Button } from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import {
EditorKeyboardShortcutsRegister,
@@ -40,10 +41,11 @@ import {
} from '../editor-canvas-container';
import SaveButton from '../save-button';
import SiteEditorMoreMenu from '../more-menu';
+import SiteIcon from '../site-icon';
import useEditorIframeProps from '../block-editor/use-editor-iframe-props';
import useEditorTitle from './use-editor-title';
-const { Editor } = unlock( editorPrivateApis );
+const { Editor, BackButton } = unlock( editorPrivateApis );
const { useHistory } = unlock( routerPrivateApis );
const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis );
@@ -125,6 +127,7 @@ export default function EditSiteEditor( { isLoading } ) {
],
[ settings.styles, canvasMode, currentPostIsTrashed ]
);
+ const { setCanvasMode } = unlock( useDispatch( editSiteStore ) );
const { createSuccessNotice } = useDispatch( noticesStore );
const history = useHistory();
const onActionPerformed = useCallback(
@@ -213,6 +216,23 @@ export default function EditSiteEditor( { isLoading } ) {
! isEditingPage &&
}
>
+ { isEditMode && (
+
+ { ( { length } ) =>
+ length <= 1 && (
+
+ )
+ }
+
+ ) }
{ supportsGlobalStyles && }
diff --git a/packages/edit-site/src/components/editor/style.scss b/packages/edit-site/src/components/editor/style.scss
index f44b5a6f02ce2..b157057062c9d 100644
--- a/packages/edit-site/src/components/editor/style.scss
+++ b/packages/edit-site/src/components/editor/style.scss
@@ -17,7 +17,3 @@
display: flex;
justify-content: center;
}
-
-.editor-header {
- padding-left: $header-height;
-}
diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js
index 4bbf29cced39e..58de32d4b4687 100644
--- a/packages/edit-site/src/components/layout/index.js
+++ b/packages/edit-site/src/components/layout/index.js
@@ -16,9 +16,10 @@ import {
useReducedMotion,
useViewportMatch,
useResizeObserver,
+ usePrevious,
} from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
-import { useState } from '@wordpress/element';
+import { useState, useRef, useEffect } from '@wordpress/element';
import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
import {
CommandMenu,
@@ -72,7 +73,7 @@ export default function Layout() {
useCommonCommands();
const isMobileViewport = useViewportMatch( 'medium', '<' );
-
+ const toggleRef = useRef();
const {
isDistractionFree,
hasFixedToolbar,
@@ -120,27 +121,6 @@ export default function Layout() {
triggerAnimationOnChange: canvasMode + '__' + routeKey,
} );
- // This determines which animation variant should apply to the header.
- // There is also a `isDistractionFreeHovering` state that gets priority
- // when hovering the `edit-site-layout__header-container` in distraction
- // free mode. It's set via framer and trickles down to all the children
- // so they can use this variant state too.
- //
- // TODO: The issue with this is we want to have the hover state stick when hovering
- // a popover opened via the header. We'll probably need to lift this state to
- // handle it ourselves. Also, focusWithin the header needs to be handled.
- let headerAnimationState;
-
- if ( canvasMode === 'view' ) {
- // We need 'view' to always take priority so 'isDistractionFree'
- // doesn't bleed over into the view (sidebar) state
- headerAnimationState = 'view';
- } else if ( isDistractionFree ) {
- headerAnimationState = 'isDistractionFree';
- } else {
- headerAnimationState = canvasMode; // edit, view, init
- }
-
// Sets the right context for the command palette
let commandContext = 'site-editor';
@@ -154,6 +134,14 @@ export default function Layout() {
const [ backgroundColor ] = useGlobalStyle( 'color.background' );
const [ gradientValue ] = useGlobalStyle( 'color.gradient' );
+ const previousCanvaMode = usePrevious( canvasMode );
+ useEffect( () => {
+ if ( previousCanvaMode === 'edit' ) {
+ toggleRef.current?.focus();
+ }
+ // Should not depend on the previous canvas mode value but the next.
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [ canvasMode ] );
// Synchronizing the URL with the store value of canvasMode happens in an effect
// This condition ensures the component is only rendered after the synchronization happens
@@ -183,41 +171,6 @@ export default function Layout() {
}
) }
>
-
-
-
-
{ /*
The NavigableRegion must always be rendered and not use
@@ -246,6 +199,12 @@ export default function Layout() {
} }
className="edit-site-layout__sidebar"
>
+
{ areas.sidebar }
diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss
index 0c5412b6d765b..01c31de0d65d6 100644
--- a/packages/edit-site/src/components/layout/style.scss
+++ b/packages/edit-site/src/components/layout/style.scss
@@ -11,37 +11,6 @@
}
}
-.edit-site-layout__hub {
- position: fixed;
- top: 0;
- left: 0;
- width: calc(100vw - #{$canvas-padding * 2});
- height: $header-height;
- z-index: z-index(".edit-site-layout__hub");
-
- @include break-medium {
- width: calc(#{$nav-sidebar-width} - #{$grid-unit-15});
- }
-
- .edit-site-layout.is-full-canvas & {
- padding-right: 0;
- border-radius: 0;
- width: $header-height;
- box-shadow: none;
- }
-}
-
-.edit-site-layout__header-container:has(+ .edit-site-layout__content > .edit-site-layout__mobile>.edit-site-page) {
- margin-bottom: $header-height;
- @include break-medium {
- margin-bottom: 0;
- }
-}
-
-.edit-site-layout__header-container {
- z-index: z-index(".edit-site-layout__header-container");
-}
-
.edit-site-layout__content {
height: 100%;
flex-grow: 1;
@@ -163,10 +132,22 @@
height: 100%;
}
+/* stylelint-disable -- Disable reason: View Transitions not supported properly by stylelint. */
+html.canvas-mode-edit-transition::view-transition-group(toggle) {
+ animation-delay: 255ms;
+}
+/* stylelint-enable */
+
+.edit-site-layout.is-full-canvas .edit-site-layout__sidebar-region .edit-site-layout__view-mode-toggle {
+ display: none;
+}
+
.edit-site-layout__view-mode-toggle.components-button {
+ /* stylelint-disable -- Disable reason: View Transitions not supported properly by stylelint. */
+ view-transition-name: toggle;
+ /* stylelint-enable */
position: relative;
color: $white;
- border-radius: 0;
height: $header-height;
width: $header-height;
overflow: hidden;
@@ -174,6 +155,8 @@
display: flex;
align-items: center;
justify-content: center;
+ background: $gray-900;
+ border-radius: 0;
&:hover,
&:active {
@@ -207,7 +190,6 @@
.edit-site-layout__view-mode-toggle-icon {
display: flex;
- border-radius: $radius-block-ui;
height: $grid-unit-80;
width: $grid-unit-80;
justify-content: center;
@@ -244,33 +226,6 @@
}
}
-.edit-site-layout.is-distraction-free {
- .edit-site-layout__header-container {
- height: $header-height;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- z-index: z-index(".edit-site-layout__header-container");
- width: 100%;
-
- // We need ! important because we override inline styles
- // set by the motion component.
- &:focus-within {
- opacity: 1 !important;
- div {
- transform: translateX(0) translateY(0) translateZ(0) !important;
- }
- }
- }
-
- .edit-site-site-hub {
- position: absolute;
- top: 0;
- z-index: z-index(".edit-site-layout__hub");
- }
-}
-
.edit-site-layout__area {
flex-grow: 1;
margin: 0;
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
index 7691f9ba2cdb0..43b789d669ba4 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
@@ -59,7 +59,7 @@
position: sticky;
top: 0;
background: $gray-900;
- padding-top: $grid-unit-60 + $header-height;
+ padding-top: $grid-unit-60;
margin-bottom: $grid-unit-10;
padding-bottom: $grid-unit-10;
z-index: z-index(".edit-site-sidebar-navigation-screen__title-icon");
diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js
index 160015a4bf3b1..b53fed2d7a94f 100644
--- a/packages/edit-site/src/components/site-hub/index.js
+++ b/packages/edit-site/src/components/site-hub/index.js
@@ -7,19 +7,11 @@ import clsx from 'clsx';
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
-import {
- Button,
- __unstableMotion as motion,
- __unstableAnimatePresence as AnimatePresence,
- __experimentalHStack as HStack,
-} from '@wordpress/components';
-import { useReducedMotion } from '@wordpress/compose';
+import { Button, __experimentalHStack as HStack } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
-import { store as blockEditorStore } from '@wordpress/block-editor';
import { store as coreStore } from '@wordpress/core-data';
-import { store as editorStore } from '@wordpress/editor';
import { decodeEntities } from '@wordpress/html-entities';
-import { memo } from '@wordpress/element';
+import { memo, forwardRef } from '@wordpress/element';
import { search } from '@wordpress/icons';
import { store as commandsStore } from '@wordpress/commands';
import { displayShortcut } from '@wordpress/keycodes';
@@ -32,14 +24,10 @@ import { store as editSiteStore } from '../../store';
import SiteIcon from '../site-icon';
import { unlock } from '../../lock-unlock';
-const HUB_ANIMATION_DURATION = 0.3;
-
-const SiteHub = memo( ( { isTransparent, className } ) => {
- const { canvasMode, dashboardLink, homeUrl, siteTitle } = useSelect(
- ( select ) => {
- const { getCanvasMode, getSettings } = unlock(
- select( editSiteStore )
- );
+const SiteHub = memo(
+ forwardRef( ( { isTransparent }, ref ) => {
+ const { dashboardLink, homeUrl, siteTitle } = useSelect( ( select ) => {
+ const { getSettings } = unlock( select( editSiteStore ) );
const {
getSite,
@@ -47,7 +35,6 @@ const SiteHub = memo( ( { isTransparent, className } ) => {
} = select( coreStore );
const _site = getSite();
return {
- canvasMode: getCanvasMode(),
dashboardLink:
getSettings().__experimentalDashboardLink || 'index.php',
homeUrl: getUnstableBase()?.home,
@@ -56,141 +43,63 @@ const SiteHub = memo( ( { isTransparent, className } ) => {
? filterURLForDisplay( _site?.url )
: _site?.title,
};
- },
- []
- );
- const { open: openCommandCenter } = useDispatch( commandsStore );
-
- const disableMotion = useReducedMotion();
- const { setCanvasMode } = unlock( useDispatch( editSiteStore ) );
- const { clearSelectedBlock } = useDispatch( blockEditorStore );
- const { setDeviceType } = useDispatch( editorStore );
- const isBackToDashboardButton = canvasMode === 'view';
- const siteIconButtonProps = isBackToDashboardButton
- ? {
- href: dashboardLink,
- label: __( 'Go to the Dashboard' ),
- }
- : {
- href: dashboardLink, // We need to keep the `href` here so the component doesn't remount as a `
+ );
+ } )
+);
export default SiteHub;
diff --git a/packages/edit-site/src/components/site-hub/style.scss b/packages/edit-site/src/components/site-hub/style.scss
index 072dcbeb94f26..7fae845d4d203 100644
--- a/packages/edit-site/src/components/site-hub/style.scss
+++ b/packages/edit-site/src/components/site-hub/style.scss
@@ -3,6 +3,7 @@
align-items: center;
justify-content: space-between;
gap: $grid-unit-10;
+ margin-right: $grid-unit-15;
}
.edit-site-site-hub__actions {
@@ -14,10 +15,6 @@
width: $header-height;
flex-shrink: 0;
- .edit-site-layout__view-mode-toggle-icon {
- background: $gray-900;
- }
-
&.has-transparent-background .edit-site-layout__view-mode-toggle-icon {
background: transparent;
}
diff --git a/packages/edit-site/src/components/site-icon/style.scss b/packages/edit-site/src/components/site-icon/style.scss
index d8b5e3f9b51de..a461b43476fe5 100644
--- a/packages/edit-site/src/components/site-icon/style.scss
+++ b/packages/edit-site/src/components/site-icon/style.scss
@@ -1,8 +1,5 @@
.edit-site-site-icon__icon {
fill: currentColor;
- // Matches SiteIcon motion, smoothing out the transition.
- transition: padding 0.3s ease-out;
- @include reduce-motion("transition");
.edit-site-layout.is-full-canvas & {
// Make the WordPress icon not so big in full canvas.
@@ -13,7 +10,6 @@
.edit-site-site-icon__image {
width: 100%;
height: 100%;
- border-radius: $radius-block-ui * 2;
object-fit: cover;
background: #333;
diff --git a/packages/edit-site/src/store/private-actions.js b/packages/edit-site/src/store/private-actions.js
index c40e1c5fc366a..bd56e30f10d11 100644
--- a/packages/edit-site/src/store/private-actions.js
+++ b/packages/edit-site/src/store/private-actions.js
@@ -13,39 +13,67 @@ import { store as editorStore } from '@wordpress/editor';
export const setCanvasMode =
( mode ) =>
( { registry, dispatch } ) => {
- const isMediumOrBigger =
- window.matchMedia( '(min-width: 782px)' ).matches;
- registry.dispatch( blockEditorStore ).__unstableSetEditorMode( 'edit' );
- const isPublishSidebarOpened = registry
- .select( editorStore )
- .isPublishSidebarOpened();
- dispatch( {
- type: 'SET_CANVAS_MODE',
- mode,
- } );
- const isEditMode = mode === 'edit';
- if ( isPublishSidebarOpened && ! isEditMode ) {
- registry.dispatch( editorStore ).closePublishSidebar();
- }
+ const switchCanvasMode = () => {
+ registry.batch( () => {
+ const isMediumOrBigger =
+ window.matchMedia( '(min-width: 782px)' ).matches;
+ registry.dispatch( blockEditorStore ).clearSelectedBlock();
+ registry.dispatch( editorStore ).setDeviceType( 'Desktop' );
+ registry
+ .dispatch( blockEditorStore )
+ .__unstableSetEditorMode( 'edit' );
+ const isPublishSidebarOpened = registry
+ .select( editorStore )
+ .isPublishSidebarOpened();
+ dispatch( {
+ type: 'SET_CANVAS_MODE',
+ mode,
+ } );
+ const isEditMode = mode === 'edit';
+ if ( isPublishSidebarOpened && ! isEditMode ) {
+ registry.dispatch( editorStore ).closePublishSidebar();
+ }
+
+ // Check if the block list view should be open by default.
+ // If `distractionFree` mode is enabled, the block list view should not be open.
+ // This behavior is disabled for small viewports.
+ if (
+ isMediumOrBigger &&
+ isEditMode &&
+ registry
+ .select( preferencesStore )
+ .get( 'core', 'showListViewByDefault' ) &&
+ ! registry
+ .select( preferencesStore )
+ .get( 'core', 'distractionFree' )
+ ) {
+ registry
+ .dispatch( editorStore )
+ .setIsListViewOpened( true );
+ } else {
+ registry
+ .dispatch( editorStore )
+ .setIsListViewOpened( false );
+ }
+ registry.dispatch( editorStore ).setIsInserterOpened( false );
+ } );
+ };
- // Check if the block list view should be open by default.
- // If `distractionFree` mode is enabled, the block list view should not be open.
- // This behavior is disabled for small viewports.
- if (
- isMediumOrBigger &&
- isEditMode &&
- registry
- .select( preferencesStore )
- .get( 'core', 'showListViewByDefault' ) &&
- ! registry
- .select( preferencesStore )
- .get( 'core', 'distractionFree' )
- ) {
- registry.dispatch( editorStore ).setIsListViewOpened( true );
+ if ( ! document.startViewTransition ) {
+ switchCanvasMode();
} else {
- registry.dispatch( editorStore ).setIsListViewOpened( false );
+ document.documentElement.classList.add(
+ `canvas-mode-${ mode }-transition`
+ );
+ const transition = document.startViewTransition( () =>
+ switchCanvasMode()
+ );
+ transition.finished.finally( () => {
+ document.documentElement.classList.remove(
+ `canvas-mode-${ mode }-transition`
+ );
+ } );
}
- registry.dispatch( editorStore ).setIsInserterOpened( false );
};
/**
diff --git a/test/e2e/specs/site-editor/template-part.spec.js b/test/e2e/specs/site-editor/template-part.spec.js
index f1e317e171736..d88273574bc4b 100644
--- a/test/e2e/specs/site-editor/template-part.spec.js
+++ b/test/e2e/specs/site-editor/template-part.spec.js
@@ -57,8 +57,7 @@ test.describe( 'Template Part', () => {
page,
} ) => {
// Visit the index.
- await admin.visitSiteEditor();
- await editor.canvas.locator( 'body' ).click();
+ await admin.visitSiteEditor( { canvas: 'edit' } );
const headerTemplateParts = editor.canvas.locator(
'[data-type="core/template-part"]'
);
@@ -84,8 +83,7 @@ test.describe( 'Template Part', () => {
} ) => {
const paragraphText = 'Test 2';
- await admin.visitSiteEditor();
- await editor.canvas.locator( 'body' ).click();
+ await admin.visitSiteEditor( { canvas: 'edit' } );
// Add a block and select it.
await editor.insertBlock( {
name: 'core/paragraph',
@@ -124,8 +122,7 @@ test.describe( 'Template Part', () => {
const paragraphText1 = 'Test 3';
const paragraphText2 = 'Test 4';
- await admin.visitSiteEditor();
- await editor.canvas.locator( 'body' ).click();
+ await admin.visitSiteEditor( { canvas: 'edit' } );
// Add a block and select it.
await editor.insertBlock( {
name: 'core/paragraph',
@@ -199,8 +196,7 @@ test.describe( 'Template Part', () => {
} );
// Visit the index.
- await admin.visitSiteEditor();
- await editor.canvas.locator( 'body' ).click();
+ await admin.visitSiteEditor( { canvas: 'edit' } );
// Check that the header contains the paragraph added earlier.
const paragraph = editor.canvas.locator(
`p >> text="${ paragraphText }"`
@@ -303,8 +299,7 @@ test.describe( 'Template Part', () => {
editor,
page,
} ) => {
- await admin.visitSiteEditor();
- await editor.canvas.locator( 'body' ).click();
+ await admin.visitSiteEditor( { canvas: 'edit' } );
// Add a block and select it.
await editor.insertBlock( {
@@ -344,8 +339,7 @@ test.describe( 'Template Part', () => {
editor,
page,
} ) => {
- await admin.visitSiteEditor();
- await editor.canvas.locator( 'body' ).click();
+ await admin.visitSiteEditor( { canvas: 'edit' } );
// Select existing header template part.
await editor.selectBlocks(
diff --git a/test/e2e/specs/site-editor/template-revert.spec.js b/test/e2e/specs/site-editor/template-revert.spec.js
index 5c19ed5a39e00..1f8d9ea73d7fd 100644
--- a/test/e2e/specs/site-editor/template-revert.spec.js
+++ b/test/e2e/specs/site-editor/template-revert.spec.js
@@ -20,10 +20,9 @@ test.describe( 'Template Revert', () => {
await requestUtils.deleteAllTemplates( 'wp_template_part' );
await requestUtils.activateTheme( 'twentytwentyone' );
} );
- test.beforeEach( async ( { admin, requestUtils, editor } ) => {
+ test.beforeEach( async ( { admin, requestUtils } ) => {
await requestUtils.deleteAllTemplates( 'wp_template' );
- await admin.visitSiteEditor();
- await editor.canvas.locator( 'body' ).click();
+ await admin.visitSiteEditor( { canvas: 'edit' } );
} );
test( 'should delete the template after saving the reverted template', async ( {