From 1e2d8b0df1147b144aea91406e3a71740f3785e9 Mon Sep 17 00:00:00 2001
From: Andrei Draganescu
Date: Mon, 10 Oct 2022 19:30:53 +0300
Subject: [PATCH] Introduce distraction free mode (#41740)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* enhances the effect of the reduceUI preference
- hide all the chrome of the editor, including the block toolbar, top bar, most top bar buttons, insertion point and closes any sidebars
Co-authored-by: Matias Ventura <548849+mtias@users.noreply.github.com>
Co-authored-by: James Koster <846565+jameskoster@users.noreply.github.com>
* snapshot update
* remove useless prop
* Adds framer motion animation to header elements in distraction free mode.
Co-authored-by: Matias Ventura <548849+mtias@users.noreply.github.com>
Co-authored-by: James Koster <846565+jameskoster@users.noreply.github.com>
* Adjusts the bottom distance of snackbars for distraction free mode.
Co-authored-by: Javier Arce <4933+javierarce@users.noreply.github.com>
* Deals with editor notices:
- moves them to the header of the interface skeleton
- moves them on top of the interface header to make them dismissable
Co-authored-by: Javier Arce <4933+javierarce@users.noreply.github.com>
Co-authored-by: Joen A. <1204802+jasmussen@users.noreply.github.com>
* Limits notices in interface header only when distraction free mode is on.
Co-authored-by: Matias Ventura <548849+mtias@users.noreply.github.com>
* Handles toolbar focus in distraction free mode:
- Shift+Tab shows the top toolbar and allos reverse tabbing
- Alt+F10 is disabled like in other situations when focusin the toolbar not possible
Co-authored-by: Alex Stine <13755480+alexstine@users.noreply.github.com>
* Removes wrong visual margin artefact for notifications in DFM
Co-authored-by: Javier Arce <4933+javierarce@users.noreply.github.com>
* refactores reducedUI to distractionFree and hasReducedUI to isDistractionFree
* Fixes the page jump in distraction free mode.
Part of this bug but with a different cause exists in trunk as well.
Co-authored-by: Ella van Durpe <4710635+ellatrix@users.noreply.github.com>
* Bulk adds the same distraction free mode toggle effects to:
- toggle in the writing menu
- the keyboard shortcut
- the preference toggle
Adds a new action to set a feature to a desired value.
Some duplication, not sure how to DRY.
* Removes "reduce UI" from the prefferences modal.
Co-authored-by: Matias Ventura <548849+mtias@users.noreply.github.com>
* adds back slash to allowed chars in shortcuts visual expression
* fix snapshot and pref modal test
* fix pref modal bug introduced by prev commit
* use only one useSelect for easier mock implementation
* adds correct order of mocked return values for useSelect
* fix order of flags in the prefferences modal
* Moves focus on distraction free toggle to first block via block selection. Unclear what to do when there is not a post edited by a block editor, but one where the flow of the block list is not linear.
Co-authored-by: Alex Stine <13755480+alexstine@users.noreply.github.com>
* Remove double border in header and add subtle backdrop transparency.
* Let's not use "Toggle interface" as a name.
* Removes the inline toolbar in distraction free mode.
For those who have tested this PR run this in console to unset the preference, which is not otherwise visible anywhere:
```
wp.data.dispatch( 'core/preferences' ).set('core/edit-post', 'inlineToolbar', false);
```
Co-authored-by: Matias Ventura <548849+mtias@users.noreply.github.com>
* Adds the mode selector, undo, redo and doc stats back to the toolbar.
Co-authored-by: Matias Ventura <548849+mtias@users.noreply.github.com>
* creates the distraction free experiment
* Revert "creates the distraction free experiment"
This reverts commit 4565b66ea427475a58ec74a98b01fb52c56be47d.
* Combines two css rules into one.
Co-authored-by: Matias Ventura <548849+mtias@users.noreply.github.com>
* Undo a new public API `setFeature` in the prefferences package.
Use the store directly instead.
Co-authored-by: Daniel Richards <677833+talldan@users.noreply.github.com>
* Fixes small nits in code.
Co-authored-by: Ben Dwyer <275961+scruffian@users.noreply.github.com>
Co-authored-by: Matias Ventura <548849+mtias@users.noreply.github.com>
Co-authored-by: James Koster <846565+jameskoster@users.noreply.github.com>
Co-authored-by: Javier Arce <4933+javierarce@users.noreply.github.com>
Co-authored-by: Joen A. <1204802+jasmussen@users.noreply.github.com>
Co-authored-by: Alex Stine <13755480+alexstine@users.noreply.github.com>
Co-authored-by: Ella van Durpe <4710635+ellatrix@users.noreply.github.com>
Co-authored-by: Matías Ventura
Co-authored-by: Daniel Richards <677833+talldan@users.noreply.github.com>
Co-authored-by: Ben Dwyer <275961+scruffian@users.noreply.github.com>
---
.../block-list/use-in-between-inserter.js | 2 +-
.../components/block-parent-selector/index.js | 6 +-
.../block-settings-dropdown.js | 6 +-
.../src/components/block-toolbar/index.js | 10 ++--
.../components/block-tools/insertion-point.js | 12 ++++
.../block-tools/selected-block-popover.js | 15 ++++-
.../edit-post/src/components/header/index.js | 43 +++++++++++----
.../src/components/header/more-menu/index.js | 2 +-
.../src/components/header/style.scss | 44 +++++++++++++++
.../components/header/writing-menu/index.js | 55 ++++++++++++++++++-
.../components/keyboard-shortcuts/index.js | 52 +++++++++++++++++-
.../edit-post/src/components/layout/index.js | 21 +++++--
.../src/components/layout/style.scss | 7 +++
.../src/components/preferences-modal/index.js | 54 +++++++++++-------
.../options/enable-feature.js | 7 ++-
.../test/__snapshots__/index.js.snap | 16 +++---
.../preferences-modal/test/index.js | 6 +-
packages/edit-post/src/editor.js | 8 +--
.../provider/use-block-editor-settings.js | 2 +-
.../components/interface-skeleton/index.js | 36 +++++++++++-
packages/keycodes/src/index.js | 2 +-
.../preference-toggle-menu-item/index.js | 4 ++
22 files changed, 332 insertions(+), 78 deletions(-)
diff --git a/packages/block-editor/src/components/block-list/use-in-between-inserter.js b/packages/block-editor/src/components/block-list/use-in-between-inserter.js
index 22ad418d2e7297..2053c8f3eb4fc9 100644
--- a/packages/block-editor/src/components/block-list/use-in-between-inserter.js
+++ b/packages/block-editor/src/components/block-list/use-in-between-inserter.js
@@ -15,7 +15,7 @@ export function useInBetweenInserter() {
const openRef = useContext( InsertionPointOpenRef );
const isInBetweenInserterDisabled = useSelect(
( select ) =>
- select( blockEditorStore ).getSettings().hasReducedUI ||
+ select( blockEditorStore ).getSettings().isDistractionFree ||
select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out',
[]
);
diff --git a/packages/block-editor/src/components/block-parent-selector/index.js b/packages/block-editor/src/components/block-parent-selector/index.js
index caf488ac06ec6f..e338a10f170695 100644
--- a/packages/block-editor/src/components/block-parent-selector/index.js
+++ b/packages/block-editor/src/components/block-parent-selector/index.js
@@ -24,7 +24,7 @@ import { store as blockEditorStore } from '../../store';
export default function BlockParentSelector() {
const { selectBlock, toggleBlockHighlight } =
useDispatch( blockEditorStore );
- const { firstParentClientId, shouldHide, hasReducedUI } = useSelect(
+ const { firstParentClientId, shouldHide, isDistractionFree } = useSelect(
( select ) => {
const {
getBlockName,
@@ -46,7 +46,7 @@ export default function BlockParentSelector() {
'__experimentalParentSelector',
true
),
- hasReducedUI: settings.hasReducedUI,
+ isDistractionFree: settings.isDistractionFree,
};
},
[]
@@ -59,7 +59,7 @@ export default function BlockParentSelector() {
const { gestures: showMoversGestures } = useShowMoversGestures( {
ref: nodeRef,
onChange( isFocused ) {
- if ( isFocused && hasReducedUI ) {
+ if ( isFocused && isDistractionFree ) {
return;
}
toggleBlockHighlight( firstParentClientId, isFocused );
diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js
index 97ef1c52b6dd97..2076b4bb49091d 100644
--- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js
+++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js
@@ -63,7 +63,7 @@ export function BlockSettingsDropdown( {
const firstBlockClientId = blockClientIds[ 0 ];
const {
firstParentClientId,
- hasReducedUI,
+ isDistractionFree,
onlyBlock,
parentBlockType,
previousBlockClientId,
@@ -90,7 +90,7 @@ export function BlockSettingsDropdown( {
return {
firstParentClientId: _firstParentClientId,
- hasReducedUI: getSettings().hasReducedUI,
+ isDistractionFree: getSettings().isDistractionFree,
onlyBlock: 1 === getBlockCount(),
parentBlockType:
getActiveBlockVariation(
@@ -182,7 +182,7 @@ export function BlockSettingsDropdown( {
const { gestures: showParentOutlineGestures } = useShowMoversGestures( {
ref: selectParentButtonRef,
onChange( isFocused ) {
- if ( isFocused && hasReducedUI ) {
+ if ( isFocused && isDistractionFree ) {
return;
}
toggleBlockHighlight( firstParentClientId, isFocused );
diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js
index 07d4e861f60947..b2160b3db4b6b6 100644
--- a/packages/block-editor/src/components/block-toolbar/index.js
+++ b/packages/block-editor/src/components/block-toolbar/index.js
@@ -34,7 +34,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
blockClientId,
blockType,
hasFixedToolbar,
- hasReducedUI,
+ isDistractionFree,
isValid,
isVisual,
isContentLocked,
@@ -60,7 +60,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
selectedBlockClientId &&
getBlockType( getBlockName( selectedBlockClientId ) ),
hasFixedToolbar: settings.hasFixedToolbar,
- hasReducedUI: settings.hasReducedUI,
+ isDistractionFree: settings.isDistractionFree,
rootClientId: blockRootClientId,
isValid: selectedBlockClientIds.every( ( id ) =>
isBlockValid( id )
@@ -82,7 +82,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
{
ref: nodeRef,
onChange( isFocused ) {
- if ( isFocused && hasReducedUI ) {
+ if ( isFocused && isDistractionFree ) {
return;
}
toggleBlockHighlight( blockClientId, isFocused );
@@ -132,9 +132,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
) }
) }
diff --git a/packages/block-editor/src/components/block-tools/insertion-point.js b/packages/block-editor/src/components/block-tools/insertion-point.js
index 005e372ff2388d..4f98a29a6e0efb 100644
--- a/packages/block-editor/src/components/block-tools/insertion-point.js
+++ b/packages/block-editor/src/components/block-tools/insertion-point.js
@@ -33,6 +33,8 @@ function InsertionPointPopover( {
nextClientId,
rootClientId,
isInserterShown,
+ isDistractionFree,
+ isNavigationMode,
} = useSelect( ( select ) => {
const {
getBlockOrder,
@@ -41,6 +43,8 @@ function InsertionPointPopover( {
isBlockBeingDragged,
getPreviousBlockClientId,
getNextBlockClientId,
+ getSettings,
+ isNavigationMode: _isNavigationMode,
} = select( blockEditorStore );
const insertionPoint = getBlockInsertionPoint();
const order = getBlockOrder( insertionPoint.rootClientId );
@@ -60,6 +64,8 @@ function InsertionPointPopover( {
_nextClientId = getNextBlockClientId( _nextClientId );
}
+ const settings = getSettings();
+
return {
previousClientId: _previousClientId,
nextClientId: _nextClientId,
@@ -67,6 +73,8 @@ function InsertionPointPopover( {
getBlockListSettings( insertionPoint.rootClientId )
?.orientation || 'vertical',
rootClientId: insertionPoint.rootClientId,
+ isNavigationMode: _isNavigationMode(),
+ isDistractionFree: settings.isDistractionFree,
isInserterShown: insertionPoint?.__unstableWithInserter,
};
}, [] );
@@ -161,6 +169,10 @@ function InsertionPointPopover( {
},
};
+ if ( isDistractionFree && ! isNavigationMode ) {
+ return null;
+ }
+
const className = classnames(
'block-editor-block-list__insertion-point',
'is-' + orientation
diff --git a/packages/block-editor/src/components/block-tools/selected-block-popover.js b/packages/block-editor/src/components/block-tools/selected-block-popover.js
index 530a3b7bdc263d..44dd9b04b31359 100644
--- a/packages/block-editor/src/components/block-tools/selected-block-popover.js
+++ b/packages/block-editor/src/components/block-tools/selected-block-popover.js
@@ -36,6 +36,7 @@ function selector( select ) {
isMultiSelecting: isMultiSelecting(),
isTyping: isTyping(),
hasFixedToolbar: getSettings().hasFixedToolbar,
+ isDistractionFree: getSettings().isDistractionFree,
lastClientId: hasMultiSelection()
? getLastMultiSelectedBlockClientId()
: null,
@@ -46,6 +47,7 @@ function SelectedBlockPopover( {
clientId,
rootClientId,
isEmptyDefaultBlock,
+ showContents, // we may need to mount an empty popover because we reuse
capturingClientId,
__unstablePopoverSlot,
__unstableContentRef,
@@ -55,6 +57,7 @@ function SelectedBlockPopover( {
isMultiSelecting,
isTyping,
hasFixedToolbar,
+ isDistractionFree,
lastClientId,
} = useSelect( selector, [] );
const isInsertionPointVisible = useSelect(
@@ -94,6 +97,7 @@ function SelectedBlockPopover( {
editorMode === 'edit' &&
! shouldShowContextualToolbar &&
! hasFixedToolbar &&
+ ! isDistractionFree &&
! isEmptyDefaultBlock;
useShortcut(
@@ -136,7 +140,7 @@ function SelectedBlockPopover( {
resize={ false }
{ ...popoverProps }
>
- { shouldShowContextualToolbar && (
+ { shouldShowContextualToolbar && showContents && (
( {
hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(),
@@ -38,28 +38,47 @@ function Header( { setEntitiesSavedStatesCallback } ) {
isSaving: select( editPostStore ).isSavingMetaBoxes(),
showIconLabels:
select( editPostStore ).isFeatureActive( 'showIconLabels' ),
- hasReducedUI:
- select( editPostStore ).isFeatureActive( 'reducedUI' ),
} ),
[]
);
const isLargeViewport = useViewportMatch( 'large' );
- const classes = classnames( 'edit-post-header', {
- 'has-reduced-ui': hasReducedUI,
- } );
+ const classes = classnames( 'edit-post-header' );
+
+ const slideY = {
+ hidden: isDistractionFree ? { y: '-50' } : { y: 0 },
+ hover: { y: 0, transition: { type: 'tween', delay: 0.2 } },
+ };
+
+ const slideX = {
+ hidden: isDistractionFree ? { x: '-100%' } : { x: 0 },
+ hover: { x: 0, transition: { type: 'tween', delay: 0.2 } },
+ };
return (
-
+
+
+
-
+
-
-
+
+
{ ! isPublishSidebarOpened && (
// This button isn't completely hidden by the publish sidebar.
// We can't hide the whole toolbar when the publish sidebar is open because
@@ -93,7 +112,7 @@ function Header( { setEntitiesSavedStatesCallback } ) {
{ showIconLabels && ! isLargeViewport && (
) }
-
+
);
}
diff --git a/packages/edit-post/src/components/header/more-menu/index.js b/packages/edit-post/src/components/header/more-menu/index.js
index 6085ce65e51e5e..e134c7ac13194d 100644
--- a/packages/edit-post/src/components/header/more-menu/index.js
+++ b/packages/edit-post/src/components/header/more-menu/index.js
@@ -36,7 +36,7 @@ const MoreMenu = ( { showIconLabels } ) => {
scope="core/edit-post"
/>
) }
-
+
.edit-post-header__settings > .editor-post-preview {
+ visibility: hidden;
+ }
+
+ & > .edit-post-header__toolbar .edit-post-header-toolbar__inserter-toggle,
+ & > .edit-post-header__toolbar .edit-post-header-toolbar__list-view-toggle,
+ & > .edit-post-header__settings > .block-editor-post-preview__dropdown,
+ & > .edit-post-header__settings > .interface-pinned-items {
+ display: none;
+ }
+
+ }
+
+ // We need ! important because we override inline styles
+ // set by the motion component.
+ .interface-interface-skeleton__header:focus-within {
+ opacity: 1 !important;
+ div {
+ transform: translateX(0) translateZ(0) !important;
+ }
+
+ }
+
+ .components-editor-notices__dismissible {
+ position: absolute;
+ z-index: 35;
+ }
+
+}
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 a6e6052fd29df3..3d6c3e75a16eab 100644
--- a/packages/edit-post/src/components/header/writing-menu/index.js
+++ b/packages/edit-post/src/components/header/writing-menu/index.js
@@ -1,13 +1,51 @@
/**
* WordPress dependencies
*/
+import { useSelect, useDispatch } from '@wordpress/data';
import { MenuGroup } from '@wordpress/components';
import { __, _x } from '@wordpress/i18n';
import { useViewportMatch } from '@wordpress/compose';
import { displayShortcut } from '@wordpress/keycodes';
-import { PreferenceToggleMenuItem } from '@wordpress/preferences';
+import {
+ PreferenceToggleMenuItem,
+ store as preferencesStore,
+} from '@wordpress/preferences';
+import { store as blockEditorStore } from '@wordpress/block-editor';
+
+/**
+ * Internal dependencies
+ */
+import { store as postEditorStore } from '../../../store';
+
+function WritingMenu( { onClose } ) {
+ const isDistractionFree = useSelect(
+ ( select ) =>
+ select( blockEditorStore ).getSettings().isDistractionFree,
+ []
+ );
+
+ const blocks = useSelect(
+ ( select ) => select( blockEditorStore ).getBlocks(),
+ []
+ );
+
+ const { setIsInserterOpened, setIsListViewOpened, closeGeneralSidebar } =
+ useDispatch( postEditorStore );
+ const { set: setPreference } = useDispatch( preferencesStore );
+
+ const { selectBlock } = useDispatch( blockEditorStore );
+
+ const toggleDistractionFree = () => {
+ setPreference( 'core/edit-post', 'fixedToolbar', false );
+ setIsInserterOpened( false );
+ setIsListViewOpened( false );
+ closeGeneralSidebar();
+ onClose();
+ if ( ! isDistractionFree ) {
+ selectBlock( blocks[ 0 ].clientId );
+ }
+ };
-function WritingMenu() {
const isLargeViewport = useViewportMatch( 'medium' );
if ( ! isLargeViewport ) {
return null;
@@ -17,6 +55,7 @@ function WritingMenu() {
+
);
}
diff --git a/packages/edit-post/src/components/keyboard-shortcuts/index.js b/packages/edit-post/src/components/keyboard-shortcuts/index.js
index c7d481ee976a4b..19aa1990f8f48a 100644
--- a/packages/edit-post/src/components/keyboard-shortcuts/index.js
+++ b/packages/edit-post/src/components/keyboard-shortcuts/index.js
@@ -7,9 +7,11 @@ import {
useShortcut,
store as keyboardShortcutsStore,
} from '@wordpress/keyboard-shortcuts';
-import { __ } from '@wordpress/i18n';
+import { __, sprintf } 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';
/**
* Internal dependencies
@@ -18,23 +20,39 @@ import { store as editPostStore } from '../../store';
function KeyboardShortcuts() {
const { getBlockSelectionStart } = useSelect( blockEditorStore );
- const { getEditorMode, isEditorSidebarOpened, isListViewOpened } =
- useSelect( editPostStore );
+ const {
+ getEditorMode,
+ isEditorSidebarOpened,
+ isListViewOpened,
+ isFeatureActive,
+ } = useSelect( editPostStore );
const isModeToggleDisabled = useSelect( ( select ) => {
const { richEditingEnabled, codeEditingEnabled } =
select( editorStore ).getEditorSettings();
return ! richEditingEnabled || ! codeEditingEnabled;
}, [] );
+ const { createInfoNotice } = useDispatch( noticesStore );
+
const {
switchEditorMode,
openGeneralSidebar,
closeGeneralSidebar,
toggleFeature,
setIsListViewOpened,
+ setIsInserterOpened,
} = useDispatch( editPostStore );
const { registerShortcut } = useDispatch( keyboardShortcutsStore );
+ const { set: setPreference } = useDispatch( preferencesStore );
+
+ const toggleDistractionFree = () => {
+ setPreference( 'core/edit-post', 'fixedToolbar', false );
+ setIsInserterOpened( false );
+ setIsListViewOpened( false );
+ closeGeneralSidebar();
+ };
+
useEffect( () => {
registerShortcut( {
name: 'core/edit-post/toggle-mode',
@@ -46,6 +64,16 @@ function KeyboardShortcuts() {
},
} );
+ registerShortcut( {
+ name: 'core/edit-post/toggle-distraction-free',
+ category: 'global',
+ description: __( 'Toggle disrtaction free mode.' ),
+ keyCombination: {
+ modifier: 'primaryShift',
+ character: '\\',
+ },
+ } );
+
registerShortcut( {
name: 'core/edit-post/toggle-fullscreen',
category: 'global',
@@ -135,6 +163,24 @@ function KeyboardShortcuts() {
toggleFeature( 'fullscreenMode' );
} );
+ useShortcut( 'core/edit-post/toggle-distraction-free', () => {
+ closeGeneralSidebar();
+ setIsListViewOpened( false );
+ toggleDistractionFree();
+ toggleFeature( 'distractionFree' );
+ const modeState = isFeatureActive( 'distractionFree' )
+ ? __( 'on' )
+ : __( 'off' );
+ createInfoNotice(
+ // translators: Mode of distraction free can be 'on' or 'off';
+ sprintf( __( 'Distraction free mode turned %s.' ), modeState ),
+ {
+ speak: true,
+ type: 'snackbar',
+ }
+ );
+ } );
+
useShortcut( 'core/edit-post/toggle-sidebar', ( event ) => {
// This shortcut has no known clashes, but use preventDefault to prevent any
// obscure shortcuts from triggering.
diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js
index d9bf9ba5cbf826..e05ec9062ec5c5 100644
--- a/packages/edit-post/src/components/layout/index.js
+++ b/packages/edit-post/src/components/layout/index.js
@@ -82,7 +82,7 @@ function Layout( { styles } ) {
isInserterOpened,
isListViewOpened,
showIconLabels,
- hasReducedUI,
+ isDistractionFree,
showBlockBreadcrumbs,
isTemplateMode,
documentLabel,
@@ -115,8 +115,8 @@ function Layout( { styles } ) {
).getAllShortcutKeyCombinations( 'core/edit-post/next-region' ),
showIconLabels:
select( editPostStore ).isFeatureActive( 'showIconLabels' ),
- hasReducedUI:
- select( editPostStore ).isFeatureActive( 'reducedUI' ),
+ isDistractionFree:
+ select( editPostStore ).isFeatureActive( 'distractionFree' ),
showBlockBreadcrumbs: select( editPostStore ).isFeatureActive(
'showBlockBreadcrumbs'
),
@@ -124,11 +124,19 @@ function Layout( { styles } ) {
documentLabel: postTypeLabel || _x( 'Document', 'noun' ),
};
}, [] );
+ const [ distractionFree, setDistractionFree ] =
+ useState( isDistractionFree );
+
+ useEffect( () => {
+ setDistractionFree( isDistractionFree );
+ }, [ isDistractionFree ] );
+
const className = classnames( 'edit-post-layout', 'is-mode-' + mode, {
'is-sidebar-opened': sidebarIsOpened,
'has-fixed-toolbar': hasFixedToolbar,
'has-metaboxes': hasActiveMetaboxes,
'show-icon-labels': showIconLabels,
+ 'is-distraction-free': isDistractionFree,
} );
const openSidebarPanel = () =>
openGeneralSidebar(
@@ -199,6 +207,7 @@ function Layout( { styles } ) {
}
+ editorNotices={ }
secondarySidebar={ secondarySidebar() }
sidebar={
( ! isMobileViewport || sidebarIsOpened ) && (
@@ -236,7 +247,7 @@ function Layout( { styles } ) {
notices={ }
content={
<>
-
+ { ! isDistractionFree && }
{ ( mode === 'text' || ! isRichEditingEnabled ) && (
) }
@@ -256,7 +267,7 @@ function Layout( { styles } ) {
>
}
footer={
- ! hasReducedUI &&
+ ! isDistractionFree &&
showBlockBreadcrumbs &&
! isMobileViewport &&
isRichEditingEnabled &&
diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss
index f030ce7cdc6b58..f785b695489e31 100644
--- a/packages/edit-post/src/components/layout/style.scss
+++ b/packages/edit-post/src/components/layout/style.scss
@@ -11,6 +11,13 @@
padding-left: 16px;
padding-right: 16px;
}
+
+.is-distraction-free {
+ .components-editor-notices__snackbar {
+ bottom: 20px;
+ }
+}
+
@include editor-left(".edit-post-layout .components-editor-notices__snackbar");
.edit-post-layout .editor-post-publish-panel {
diff --git a/packages/edit-post/src/components/preferences-modal/index.js b/packages/edit-post/src/components/preferences-modal/index.js
index 9e3e1a53f4a870..8bba0691261a62 100644
--- a/packages/edit-post/src/components/preferences-modal/index.js
+++ b/packages/edit-post/src/components/preferences-modal/index.js
@@ -24,6 +24,7 @@ import {
PreferencesModalTabs,
PreferencesModalSection,
} from '@wordpress/interface';
+import { store as preferencesStore } from '@wordpress/preferences';
/**
* Internal dependencies
@@ -44,26 +45,40 @@ const MODAL_NAME = 'edit-post/preferences';
export default function EditPostPreferencesModal() {
const isLargeViewport = useViewportMatch( 'medium' );
const { closeModal } = useDispatch( editPostStore );
- const isModalActive = useSelect(
- ( select ) => select( editPostStore ).isModalActive( MODAL_NAME ),
- []
- );
- const showBlockBreadcrumbsOption = useSelect(
+ const [ isModalActive, showBlockBreadcrumbsOption ] = useSelect(
( select ) => {
const { getEditorSettings } = select( editorStore );
const { getEditorMode, isFeatureActive } = select( editPostStore );
+ const modalActive =
+ select( editPostStore ).isModalActive( MODAL_NAME );
const mode = getEditorMode();
const isRichEditingEnabled = getEditorSettings().richEditingEnabled;
- const hasReducedUI = isFeatureActive( 'reducedUI' );
- return (
- ! hasReducedUI &&
- isLargeViewport &&
- isRichEditingEnabled &&
- mode === 'visual'
- );
+ const isDistractionFreeEnabled =
+ isFeatureActive( 'distractionFree' );
+ return [
+ modalActive,
+ ! isDistractionFreeEnabled &&
+ isLargeViewport &&
+ isRichEditingEnabled &&
+ mode === 'visual',
+ isDistractionFreeEnabled,
+ ];
},
[ isLargeViewport ]
);
+
+ const { closeGeneralSidebar, setIsListViewOpened, setIsInserterOpened } =
+ useDispatch( editPostStore );
+
+ const { set: setPreference } = useDispatch( preferencesStore );
+
+ const toggleDistractionFree = () => {
+ setPreference( 'core/edit-post', 'fixedToolbar', false );
+ setIsInserterOpened( false );
+ setIsListViewOpened( false );
+ closeGeneralSidebar();
+ };
+
const sections = useMemo(
() => [
{
@@ -95,6 +110,14 @@ export default function EditPostPreferencesModal() {
'Customize options related to the block editor interface and editing flow.'
) }
>
+
-
( {
- onChange: () => dispatch( editPostStore ).toggleFeature( featureName ),
+ withDispatch( ( dispatch, { featureName, onToggle = () => {} } ) => ( {
+ onChange: () => {
+ onToggle();
+ dispatch( editPostStore ).toggleFeature( featureName );
+ },
} ) )
)( BaseOption );
diff --git a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/index.js.snap b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/index.js.snap
index 723d5c071d425a..95812a2828ea91 100644
--- a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/index.js.snap
+++ b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/index.js.snap
@@ -253,7 +253,7 @@ exports[`EditPostPreferencesModal should match snapshot when the modal is active
class="components-toggle-control__label"
for="inspector-toggle-control-1"
>
- Spotlight mode
+ Distraction Free
@@ -261,7 +261,7 @@ exports[`EditPostPreferencesModal should match snapshot when the modal is active
class="components-base-control__help emotion-6 emotion-7"
id="inspector-toggle-control-1__help"
>
- Highlights the current block and fades other content.
+ Reduce visual distractions by hiding the toolbar and other elements to focus on writing.
@@ -299,7 +299,7 @@ exports[`EditPostPreferencesModal should match snapshot when the modal is active
class="components-toggle-control__label"
for="inspector-toggle-control-2"
>
- Show button text labels
+ Spotlight mode
@@ -307,7 +307,7 @@ exports[`EditPostPreferencesModal should match snapshot when the modal is active
class="components-base-control__help emotion-6 emotion-7"
id="inspector-toggle-control-2__help"
>
- Show text instead of icons on buttons.
+ Highlights the current block and fades other content.
@@ -345,7 +345,7 @@ exports[`EditPostPreferencesModal should match snapshot when the modal is active
class="components-toggle-control__label"
for="inspector-toggle-control-3"
>
- Always open list view
+ Show button text labels
@@ -353,7 +353,7 @@ exports[`EditPostPreferencesModal should match snapshot when the modal is active
class="components-base-control__help emotion-6 emotion-7"
id="inspector-toggle-control-3__help"
>
- Opens the block list view sidebar by default.
+ Show text instead of icons on buttons.
@@ -391,7 +391,7 @@ exports[`EditPostPreferencesModal should match snapshot when the modal is active
class="components-toggle-control__label"
for="inspector-toggle-control-4"
>
- Reduce the interface
+ Always open list view
@@ -399,7 +399,7 @@ exports[`EditPostPreferencesModal should match snapshot when the modal is active
class="components-base-control__help emotion-6 emotion-7"
id="inspector-toggle-control-4__help"
>
- Compacts options and outlines in the toolbar.
+ Opens the block list view sidebar by default.
diff --git a/packages/edit-post/src/components/preferences-modal/test/index.js b/packages/edit-post/src/components/preferences-modal/test/index.js
index b2ab5ae2465cf2..d1ff306488cb9d 100644
--- a/packages/edit-post/src/components/preferences-modal/test/index.js
+++ b/packages/edit-post/src/components/preferences-modal/test/index.js
@@ -21,7 +21,7 @@ jest.mock( '@wordpress/compose/src/hooks/use-viewport-match', () => jest.fn() );
describe( 'EditPostPreferencesModal', () => {
describe( 'should match snapshot when the modal is active', () => {
it( 'large viewports', () => {
- useSelect.mockImplementation( () => true );
+ useSelect.mockImplementation( () => [ true, true, false ] );
useViewportMatch.mockImplementation( () => true );
render( );
expect(
@@ -29,7 +29,7 @@ describe( 'EditPostPreferencesModal', () => {
).toMatchSnapshot();
} );
it( 'small viewports', () => {
- useSelect.mockImplementation( () => true );
+ useSelect.mockImplementation( () => [ true, true, false ] );
useViewportMatch.mockImplementation( () => false );
render( );
expect(
@@ -39,7 +39,7 @@ describe( 'EditPostPreferencesModal', () => {
} );
it( 'should not render when the modal is not active', () => {
- useSelect.mockImplementation( () => false );
+ useSelect.mockImplementation( () => [ false, false, false ] );
render( );
expect(
screen.queryByRole( 'dialog', { name: 'Preferences' } )
diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js
index c7e5bbaa30d61d..06c3191ceb9f8d 100644
--- a/packages/edit-post/src/editor.js
+++ b/packages/edit-post/src/editor.js
@@ -38,7 +38,7 @@ function Editor( {
const {
hasFixedToolbar,
focusMode,
- hasReducedUI,
+ isDistractionFree,
hasInlineToolbar,
hasThemeStyles,
post,
@@ -85,7 +85,7 @@ function Editor( {
isFeatureActive( 'fixedToolbar' ) ||
__experimentalGetPreviewDeviceType() !== 'Desktop',
focusMode: isFeatureActive( 'focusMode' ),
- hasReducedUI: isFeatureActive( 'reducedUI' ),
+ isDistractionFree: isFeatureActive( 'distractionFree' ),
hasInlineToolbar: isFeatureActive( 'inlineToolbar' ),
hasThemeStyles: isFeatureActive( 'themeStyles' ),
preferredStyleVariations: select( preferencesStore ).get(
@@ -118,7 +118,7 @@ function Editor( {
},
hasFixedToolbar,
focusMode,
- hasReducedUI,
+ isDistractionFree,
hasInlineToolbar,
// This is marked as experimental to give time for the quick inserter to mature.
@@ -150,7 +150,7 @@ function Editor( {
settings,
hasFixedToolbar,
focusMode,
- hasReducedUI,
+ isDistractionFree,
hiddenBlockTypes,
blockTypes,
preferredStyleVariations,
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 95b236e85c5063..51d16ef1b6a7d6 100644
--- a/packages/editor/src/components/provider/use-block-editor-settings.js
+++ b/packages/editor/src/components/provider/use-block-editor-settings.js
@@ -159,7 +159,7 @@ function useBlockEditorSettings( settings, hasTemplate ) {
'gradients',
'generateAnchors',
'hasFixedToolbar',
- 'hasReducedUI',
+ 'isDistractionFree',
'hasInlineToolbar',
'imageDefaultSize',
'imageDimensions',
diff --git a/packages/interface/src/components/interface-skeleton/index.js b/packages/interface/src/components/interface-skeleton/index.js
index dc7b672f75325e..766ef73a2fcf56 100644
--- a/packages/interface/src/components/interface-skeleton/index.js
+++ b/packages/interface/src/components/interface-skeleton/index.js
@@ -7,7 +7,10 @@ import classnames from 'classnames';
* WordPress dependencies
*/
import { forwardRef, useEffect } from '@wordpress/element';
-import { __unstableUseNavigateRegions as useNavigateRegions } from '@wordpress/components';
+import {
+ __unstableUseNavigateRegions as useNavigateRegions,
+ __unstableMotion as motion,
+} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useMergeRefs } from '@wordpress/compose';
@@ -27,8 +30,10 @@ function useHTMLClass( className ) {
function InterfaceSkeleton(
{
+ isDistractionFree,
footer,
header,
+ editorNotices,
sidebar,
secondarySidebar,
notices,
@@ -64,6 +69,14 @@ function InterfaceSkeleton(
const mergedLabels = { ...defaultLabels, ...labels };
+ const headerVariants = {
+ hidden: isDistractionFree ? { opacity: 0 } : { opacity: 1 },
+ hover: {
+ opacity: 1,
+ transition: { type: 'tween', delay: 0.2, delayChildren: 0.2 },
+ },
+ };
+
return (
) }
- { !! header && (
+ { !! header && isDistractionFree && (
+
+ { header }
+
+ ) }
+ { !! header && ! isDistractionFree && (
) }
+ { isDistractionFree && (
+
+ { editorNotices }
+
+ ) }
{ !! secondarySidebar && (
{
// so override the rule to allow symbols used for shortcuts.
// see: https://github.com/blakeembrey/change-case#options
const capitalizedCharacter = capitalCase( character, {
- stripRegexp: /[^A-Z0-9`,\.]/gi,
+ stripRegexp: /[^A-Z0-9`,\.\\]/gi,
} );
return [ ...modifierKeys, capitalizedCharacter ];
diff --git a/packages/preferences/src/components/preference-toggle-menu-item/index.js b/packages/preferences/src/components/preference-toggle-menu-item/index.js
index 5bd6da3441a9cf..322dd236718c07 100644
--- a/packages/preferences/src/components/preference-toggle-menu-item/index.js
+++ b/packages/preferences/src/components/preference-toggle-menu-item/index.js
@@ -20,6 +20,8 @@ export default function PreferenceToggleMenuItem( {
messageActivated,
messageDeactivated,
shortcut,
+ toggleHandler = () => null,
+ disabled = false,
} ) {
const isActive = useSelect(
( select ) => !! select( preferencesStore ).get( scope, name ),
@@ -53,12 +55,14 @@ export default function PreferenceToggleMenuItem( {
icon={ isActive && check }
isSelected={ isActive }
onClick={ () => {
+ toggleHandler();
toggle( scope, name );
speakMessage();
} }
role="menuitemcheckbox"
info={ info }
shortcut={ shortcut }
+ disabled={ disabled }
>
{ label }