diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss
index 96040ec29d07b8..cc4a42df98f0aa 100644
--- a/packages/base-styles/_z-index.scss
+++ b/packages/base-styles/_z-index.scss
@@ -182,6 +182,7 @@ $z-layers: (
".customize-widgets__block-toolbar": 7,
// Site editor layout
+ ".edit-site-layout__header-container": 4,
".edit-site-layout__hub": 3,
".edit-site-layout__header": 2,
".edit-site-page-header": 2,
diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md
index 72c3d50372e48e..2c42b42afc4424 100644
--- a/packages/block-editor/README.md
+++ b/packages/block-editor/README.md
@@ -711,6 +711,7 @@ _Properties_
- _maxWidth_ `number`: Max width to constraint resizing
- _allowedBlockTypes_ `boolean|Array`: Allowed block types
- _hasFixedToolbar_ `boolean`: Whether or not the editor toolbar is fixed
+- _distractionFree_ `boolean`: Whether or not the editor UI is distraction free
- _focusMode_ `boolean`: Whether the focus mode is enabled or not
- _styles_ `Array`: Editor Styles
- _keepCaretInsideBlock_ `boolean`: Whether caret should move between blocks in edit mode
diff --git a/packages/block-editor/src/store/defaults.js b/packages/block-editor/src/store/defaults.js
index 7c33350d12dd01..acd40244cb2604 100644
--- a/packages/block-editor/src/store/defaults.js
+++ b/packages/block-editor/src/store/defaults.js
@@ -18,6 +18,7 @@ export const PREFERENCES_DEFAULTS = {
* @property {number} maxWidth Max width to constraint resizing
* @property {boolean|Array} allowedBlockTypes Allowed block types
* @property {boolean} hasFixedToolbar Whether or not the editor toolbar is fixed
+ * @property {boolean} distractionFree Whether or not the editor UI is distraction free
* @property {boolean} focusMode Whether the focus mode is enabled or not
* @property {Array} styles Editor Styles
* @property {boolean} keepCaretInsideBlock Whether caret should move between blocks in edit mode
diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js
index dfdeb2d130aa35..3f42d4736f57bb 100644
--- a/packages/edit-post/src/components/header/index.js
+++ b/packages/edit-post/src/components/header/index.js
@@ -20,6 +20,16 @@ import MainDashboardButton from './main-dashboard-button';
import { store as editPostStore } from '../../store';
import DocumentTitle from './document-title';
+const slideY = {
+ hidden: { y: '-50px' },
+ hover: { y: 0, transition: { type: 'tween', delay: 0.2 } },
+};
+
+const slideX = {
+ hidden: { x: '-100%' },
+ hover: { x: 0, transition: { type: 'tween', delay: 0.2 } },
+};
+
function Header( { setEntitiesSavedStatesCallback } ) {
const isLargeViewport = useViewportMatch( 'large' );
const {
@@ -39,16 +49,6 @@ function Header( { setEntitiesSavedStatesCallback } ) {
[]
);
- const slideY = {
- hidden: { y: '-50px' },
- hover: { y: 0, transition: { type: 'tween', delay: 0.2 } },
- };
-
- const slideX = {
- hidden: { x: '-100%' },
- hover: { x: 0, transition: { type: 'tween', delay: 0.2 } },
- };
-
return (
diff --git a/packages/edit-post/src/components/keyboard-shortcuts/index.js b/packages/edit-post/src/components/keyboard-shortcuts/index.js
index 432bce0a3bff5c..9a9574fd38bb7e 100644
--- a/packages/edit-post/src/components/keyboard-shortcuts/index.js
+++ b/packages/edit-post/src/components/keyboard-shortcuts/index.js
@@ -223,8 +223,6 @@ function KeyboardShortcuts() {
} );
useShortcut( 'core/edit-post/toggle-distraction-free', () => {
- closeGeneralSidebar();
- setIsListViewOpened( false );
toggleDistractionFree();
toggleFeature( 'distractionFree' );
createInfoNotice(
diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js
index 24805014e3d695..238cad73870553 100644
--- a/packages/edit-site/src/components/editor/index.js
+++ b/packages/edit-site/src/components/editor/index.js
@@ -180,6 +180,7 @@ export default function Editor( { isLoading } ) {
{ isEditMode && }
{ hasDefaultEditorCanvasView && (
-
+ { ! isDistractionFree && (
+
+ ) }
{ isLargeViewport && (
<>
-
- { isZoomedOutViewExperimentEnabled && (
+ { ! isDistractionFree && (
{
- setPreviewDeviceType( 'desktop' );
- __unstableSetEditorMode(
- isZoomedOutView
- ? 'edit'
- : 'zoom-out'
- );
- } }
+ label={ __( 'List View' ) }
+ onClick={ toggleListView }
+ shortcut={ listViewShortcut }
+ showTooltip={ ! showIconLabels }
+ variant={
+ showIconLabels
+ ? 'tertiary'
+ : undefined
+ }
/>
) }
+ { isZoomedOutViewExperimentEnabled &&
+ ! isDistractionFree && (
+ {
+ setPreviewDeviceType(
+ 'desktop'
+ );
+ __unstableSetEditorMode(
+ isZoomedOutView
+ ? 'edit'
+ : 'zoom-out'
+ );
+ } }
+ />
+ ) }
>
) }
) }
-
- { ! hasDefaultEditorCanvasView ? (
- getEditorCanvasContainerTitle( editorCanvasView )
- ) : (
-
- ) }
-
+ { ! isDistractionFree && (
+
+ { ! hasDefaultEditorCanvasView ? (
+ getEditorCanvasContainerTitle( editorCanvasView )
+ ) : (
+
+ ) }
+
+ ) }
-
+
{ ! isFocusMode && hasDefaultEditorCanvasView && (
) }
-
+ { ! isDistractionFree && (
+
+ ) }
-
+
);
diff --git a/packages/edit-site/src/components/header-edit-mode/more-menu/index.js b/packages/edit-site/src/components/header-edit-mode/more-menu/index.js
index a7c9ea977db176..802e9f9439811f 100644
--- a/packages/edit-site/src/components/header-edit-mode/more-menu/index.js
+++ b/packages/edit-site/src/components/header-edit-mode/more-menu/index.js
@@ -3,12 +3,16 @@
*/
import { __, _x } from '@wordpress/i18n';
import { useReducer } from '@wordpress/element';
+import { useSelect, useDispatch, useRegistry } from '@wordpress/data';
import { useShortcut } from '@wordpress/keyboard-shortcuts';
import { displayShortcut } from '@wordpress/keycodes';
import { external } from '@wordpress/icons';
import { MenuGroup, MenuItem, VisuallyHidden } from '@wordpress/components';
import { ActionItem, MoreMenuDropdown } from '@wordpress/interface';
-import { PreferenceToggleMenuItem } from '@wordpress/preferences';
+import {
+ PreferenceToggleMenuItem,
+ store as preferencesStore,
+} from '@wordpress/preferences';
/**
* Internal dependencies
@@ -20,6 +24,7 @@ import SiteExport from './site-export';
import WelcomeGuideMenuItem from './welcome-guide-menu-item';
import CopyContentMenuItem from './copy-content-menu-item';
import ModeSwitcher from '../mode-switcher';
+import { store as siteEditorStore } from '../../../store';
export default function MoreMenu( { showIconLabels } ) {
const [ isModalActive, toggleModal ] = useReducer(
@@ -32,6 +37,29 @@ export default function MoreMenu( { showIconLabels } ) {
false
);
+ const registry = useRegistry();
+ const isDistractionFree = useSelect(
+ ( select ) =>
+ select( preferencesStore ).get(
+ 'core/edit-site',
+ 'distractionFree'
+ ),
+ []
+ );
+
+ const { setIsInserterOpened, setIsListViewOpened, closeGeneralSidebar } =
+ useDispatch( siteEditorStore );
+ const { set: setPreference } = useDispatch( preferencesStore );
+
+ const toggleDistractionFree = () => {
+ registry.batch( () => {
+ setPreference( 'core/edit-site', 'fixedToolbar', false );
+ setIsInserterOpened( false );
+ setIsListViewOpened( false );
+ closeGeneralSidebar();
+ } );
+ };
+
useShortcut( 'core/edit-site/keyboard-shortcuts', toggleModal );
return (
@@ -48,6 +76,7 @@ export default function MoreMenu( { showIconLabels } ) {
+
{
+ setPreference( 'core/edit-site', 'fixedToolbar', false );
+ setIsInserterOpened( false );
+ setIsListViewOpened( false );
+ closeGeneralSidebar();
+ };
+
const handleTextLevelShortcut = ( event, level ) => {
event.preventDefault();
const destinationBlockName =
@@ -114,6 +133,20 @@ function KeyboardShortcutsEditMode() {
);
} );
+ useShortcut( 'core/edit-site/toggle-distraction-free', () => {
+ toggleDistractionFree();
+ toggleFeature( 'distractionFree' );
+ createInfoNotice(
+ isFeatureActive( 'distractionFree' )
+ ? __( 'Distraction free mode turned on.' )
+ : __( 'Distraction free mode turned off.' ),
+ {
+ id: 'core/edit-site/distraction-free-mode/notice',
+ type: 'snackbar',
+ }
+ );
+ } );
+
return null;
}
diff --git a/packages/edit-site/src/components/keyboard-shortcuts/register.js b/packages/edit-site/src/components/keyboard-shortcuts/register.js
index 9660b03e762ed6..8dfd1e3e2a45bf 100644
--- a/packages/edit-site/src/components/keyboard-shortcuts/register.js
+++ b/packages/edit-site/src/components/keyboard-shortcuts/register.js
@@ -149,6 +149,16 @@ function KeyboardShortcutsRegister() {
},
} );
} );
+
+ registerShortcut( {
+ name: 'core/edit-site/toggle-distraction-free',
+ category: 'global',
+ description: __( 'Toggle distraction free mode.' ),
+ keyCombination: {
+ modifier: 'primaryShift',
+ character: '\\',
+ },
+ } );
}, [ registerShortcut ] );
return null;
diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js
index 60d493192b9a19..3398ec332c7662 100644
--- a/packages/edit-site/src/components/layout/index.js
+++ b/packages/edit-site/src/components/layout/index.js
@@ -72,24 +72,36 @@ export default function Layout() {
const isMobileViewport = useViewportMatch( 'medium', '<' );
const isListPage = getIsListPage( params, isMobileViewport );
const isEditorPage = ! isListPage;
- const { hasFixedToolbar, canvasMode, previousShortcut, nextShortcut } =
- useSelect( ( select ) => {
- const { getAllShortcutKeyCombinations } = select(
- keyboardShortcutsStore
- );
- const { getCanvasMode } = unlock( select( editSiteStore ) );
- return {
- canvasMode: getCanvasMode(),
- previousShortcut: getAllShortcutKeyCombinations(
- 'core/edit-site/previous-region'
- ),
- nextShortcut: getAllShortcutKeyCombinations(
- 'core/edit-site/next-region'
- ),
- hasFixedToolbar:
- select( preferencesStore ).get( 'fixedToolbar' ),
- };
- }, [] );
+
+ const {
+ isDistractionFree,
+ hasFixedToolbar,
+ canvasMode,
+ previousShortcut,
+ nextShortcut,
+ } = useSelect( ( select ) => {
+ const { getAllShortcutKeyCombinations } = select(
+ keyboardShortcutsStore
+ );
+ const { getCanvasMode } = unlock( select( editSiteStore ) );
+ return {
+ canvasMode: getCanvasMode(),
+ previousShortcut: getAllShortcutKeyCombinations(
+ 'core/edit-site/previous-region'
+ ),
+ nextShortcut: getAllShortcutKeyCombinations(
+ 'core/edit-site/next-region'
+ ),
+ hasFixedToolbar: select( preferencesStore ).get(
+ 'core/edit-site',
+ 'fixedToolbar'
+ ),
+ isDistractionFree: select( preferencesStore ).get(
+ 'core/edit-site',
+ 'distractionFree'
+ ),
+ };
+ }, [] );
const isEditing = canvasMode === 'edit';
const navigateRegionsProps = useNavigateRegions( {
previous: previousShortcut,
@@ -110,6 +122,27 @@ export default function Layout() {
const [ isResizing ] = useState( false );
const isEditorLoading = useIsSiteEditorLoading();
+ // 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 center
const commandContext =
canvasMode === 'edit' && isEditorPage
@@ -140,41 +173,77 @@ export default function Layout() {
'edit-site-layout',
navigateRegionsProps.className,
{
+ 'is-distraction-free': isDistractionFree && isEditing,
'is-full-canvas': isFullCanvas,
'is-edit-mode': isEditing,
'has-fixed-toolbar': hasFixedToolbar,
}
) }
>
-
-
-
- { isEditorPage && isEditing && (
-
- { isEditing && }
-
- ) }
-
+ delay: 0.8,
+ delayChildren: 0.8,
+ }, // How long to wait before the header exits
+ },
+ isDistractionFreeHovering: {
+ opacity: 1,
+ transition: {
+ type: 'tween',
+ delay: 0.2,
+ delayChildren: 0.2,
+ }, // How long to wait before the header shows
+ },
+ view: { opacity: 1 },
+ edit: { opacity: 1 },
+ } }
+ whileHover={
+ isDistractionFree
+ ? 'isDistractionFreeHovering'
+ : undefined
+ }
+ animate={ headerAnimationState }
+ >
+
+
+
+ { isEditorPage && isEditing && (
+
+ { isEditing && }
+
+ ) }
+
+
diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss
index 2097154fa94c34..dbccc48100cf6b 100644
--- a/packages/edit-site/src/components/layout/style.scss
+++ b/packages/edit-site/src/components/layout/style.scss
@@ -36,6 +36,10 @@
}
}
+.edit-site-layout__header-container {
+ z-index: z-index(".edit-site-layout__header-container");
+}
+
.edit-site-layout__header {
height: $header-height;
display: flex;
@@ -249,6 +253,9 @@
// so the fixed toolbar can be positioned on top of it
// but only on desktop
@include break-medium() {
+ .edit-site-layout__canvas-container {
+ z-index: 5;
+ }
.edit-site-site-hub {
z-index: 4;
}
@@ -258,3 +265,42 @@
}
}
+.is-edit-mode.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-layout__header {
+ opacity: 1 !important;
+ }
+ }
+ }
+
+ .edit-site-site-hub,
+ .edit-site-layout__header {
+ position: absolute;
+ top: 0;
+ z-index: z-index(".edit-site-layout__header");
+ }
+ .edit-site-site-hub {
+ z-index: z-index(".edit-site-layout__hub");
+ }
+ .edit-site-layout__header {
+ width: 100%;
+ }
+
+}
diff --git a/packages/edit-site/src/components/preferences-modal/enable-feature.js b/packages/edit-site/src/components/preferences-modal/enable-feature.js
index ca4a8a1bb1a327..9cd2105ba69fff 100644
--- a/packages/edit-site/src/components/preferences-modal/enable-feature.js
+++ b/packages/edit-site/src/components/preferences-modal/enable-feature.js
@@ -6,14 +6,17 @@ import { ___unstablePreferencesModalBaseOption as BaseOption } from '@wordpress/
import { store as preferencesStore } from '@wordpress/preferences';
export default function EnableFeature( props ) {
- const { featureName, ...remainingProps } = props;
+ const { featureName, onToggle = () => {}, ...remainingProps } = props;
const isChecked = useSelect(
( select ) =>
!! select( preferencesStore ).get( 'core/edit-site', featureName ),
[ featureName ]
);
const { toggle } = useDispatch( preferencesStore );
- const onChange = () => toggle( 'core/edit-site', featureName );
+ const onChange = () => {
+ onToggle();
+ toggle( 'core/edit-site', featureName );
+ };
return (
{
+ registry.batch( () => {
+ setPreference( 'core/edit-site', 'fixedToolbar', false );
+ setIsInserterOpened( false );
+ setIsListViewOpened( false );
+ closeGeneralSidebar();
+ } );
+ };
+
const sections = useMemo( () => [
{
name: 'general',
@@ -29,6 +46,14 @@ export default function EditSitePreferencesModal( {
'Customize options related to the block editor interface and editing flow.'
) }
>
+
{};
export function SidebarNavigationItemGlobalStyles( props ) {
- const { openGeneralSidebar } = useDispatch( editSiteStore );
+ const { openGeneralSidebar, toggleFeature } = useDispatch( editSiteStore );
const { setCanvasMode } = unlock( useDispatch( editSiteStore ) );
+ const { createNotice } = useDispatch( noticesStore );
const hasGlobalStyleVariations = useSelect(
( select ) =>
!! select(
@@ -53,9 +55,19 @@ export function SidebarNavigationItemGlobalStyles( props ) {
{
- // switch to edit mode.
+ // Disable distraction free mode.
+ toggleFeature( 'distractionFree', false );
+ createNotice(
+ 'info',
+ __( 'Distraction free mode turned off' ),
+ {
+ isDismissible: true,
+ type: 'snackbar',
+ }
+ );
+ // Switch to edit mode.
setCanvasMode( 'edit' );
- // open global styles sidebar.
+ // Open global styles sidebar.
openGeneralSidebar( 'edit-site/global-styles' );
} }
/>
diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js
index e696a441bb10da..a4698c02aff90b 100644
--- a/packages/edit-site/src/index.js
+++ b/packages/edit-site/src/index.js
@@ -63,6 +63,7 @@ export function initializeEditor( id, settings ) {
editorMode: 'visual',
fixedToolbar: false,
focusMode: false,
+ distractionFree: false,
keepCaretInsideBlock: false,
welcomeGuide: true,
welcomeGuideStyles: true,
diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js
index e8dcd03da73416..654b3c321ae93f 100644
--- a/packages/edit-site/src/store/selectors.js
+++ b/packages/edit-site/src/store/selectors.js
@@ -107,6 +107,10 @@ export const getSettings = createSelector(
...state.settings,
outlineMode: true,
focusMode: !! __unstableGetPreference( state, 'focusMode' ),
+ isDistractionFree: !! __unstableGetPreference(
+ state,
+ 'distractionFree'
+ ),
hasFixedToolbar: !! __unstableGetPreference(
state,
'fixedToolbar'
@@ -143,6 +147,7 @@ export const getSettings = createSelector(
getCanUserCreateMedia( state ),
state.settings,
__unstableGetPreference( state, 'focusMode' ),
+ __unstableGetPreference( state, 'distractionFree' ),
__unstableGetPreference( state, 'fixedToolbar' ),
__unstableGetPreference( state, 'keepCaretInsideBlock' ),
__unstableGetPreference( state, 'showIconLabels' ),
diff --git a/packages/edit-site/src/store/test/selectors.js b/packages/edit-site/src/store/test/selectors.js
index ac4778f03c7b54..9380f8ea4d276c 100644
--- a/packages/edit-site/src/store/test/selectors.js
+++ b/packages/edit-site/src/store/test/selectors.js
@@ -77,6 +77,7 @@ describe( 'selectors', () => {
outlineMode: true,
focusMode: false,
hasFixedToolbar: false,
+ isDistractionFree: false,
keepCaretInsideBlock: false,
showIconLabels: false,
__experimentalSetIsInserterOpened: setInserterOpened,
@@ -102,6 +103,7 @@ describe( 'selectors', () => {
key: 'value',
focusMode: true,
hasFixedToolbar: true,
+ isDistractionFree: false,
keepCaretInsideBlock: false,
showIconLabels: false,
__experimentalSetIsInserterOpened: setInserterOpened,
diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js
index 8a71fb5deca65f..400e6799996ccb 100644
--- a/packages/editor/src/components/provider/use-block-editor-settings.js
+++ b/packages/editor/src/components/provider/use-block-editor-settings.js
@@ -47,6 +47,7 @@ const BLOCK_EDITOR_SETTINGS = [
'enableCustomUnits',
'enableOpenverseMediaCategory',
'focusMode',
+ 'distractionFree',
'fontSizes',
'gradients',
'generateAnchors',
diff --git a/packages/interface/src/components/interface-skeleton/index.js b/packages/interface/src/components/interface-skeleton/index.js
index 43e4e532e8eab3..baf98d153ed870 100644
--- a/packages/interface/src/components/interface-skeleton/index.js
+++ b/packages/interface/src/components/interface-skeleton/index.js
@@ -33,6 +33,15 @@ function useHTMLClass( className ) {
}, [ className ] );
}
+const headerVariants = {
+ hidden: { opacity: 0 },
+ hover: {
+ opacity: 1,
+ transition: { type: 'tween', delay: 0.2, delayChildren: 0.2 },
+ },
+ distractionFreeInactive: { opacity: 1, transition: { delay: 0 } },
+};
+
function InterfaceSkeleton(
{
isDistractionFree,
@@ -74,15 +83,6 @@ function InterfaceSkeleton(
const mergedLabels = { ...defaultLabels, ...labels };
- const headerVariants = {
- hidden: { opacity: 0 },
- hover: {
- opacity: 1,
- transition: { type: 'tween', delay: 0.2, delayChildren: 0.2 },
- },
- distractionFreeInactive: { opacity: 1, transition: { delay: 0 } },
- };
-
return (