Skip to content

Commit

Permalink
Introduce distraction free mode (#41740)
Browse files Browse the repository at this point in the history
* 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 4565b66.

* 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 <mv@matiasventura.com>
Co-authored-by: Daniel Richards <677833+talldan@users.noreply.github.com>
Co-authored-by: Ben Dwyer <275961+scruffian@users.noreply.github.com>
  • Loading branch information
10 people authored Oct 10, 2022
1 parent 6c4ee99 commit 1e2d8b0
Show file tree
Hide file tree
Showing 22 changed files with 332 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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',
[]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -46,7 +46,7 @@ export default function BlockParentSelector() {
'__experimentalParentSelector',
true
),
hasReducedUI: settings.hasReducedUI,
isDistractionFree: settings.isDistractionFree,
};
},
[]
Expand All @@ -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 );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function BlockSettingsDropdown( {
const firstBlockClientId = blockClientIds[ 0 ];
const {
firstParentClientId,
hasReducedUI,
isDistractionFree,
onlyBlock,
parentBlockType,
previousBlockClientId,
Expand All @@ -90,7 +90,7 @@ export function BlockSettingsDropdown( {

return {
firstParentClientId: _firstParentClientId,
hasReducedUI: getSettings().hasReducedUI,
isDistractionFree: getSettings().isDistractionFree,
onlyBlock: 1 === getBlockCount(),
parentBlockType:
getActiveBlockVariation(
Expand Down Expand Up @@ -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 );
Expand Down
10 changes: 4 additions & 6 deletions packages/block-editor/src/components/block-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
blockClientId,
blockType,
hasFixedToolbar,
hasReducedUI,
isDistractionFree,
isValid,
isVisual,
isContentLocked,
Expand All @@ -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 )
Expand All @@ -82,7 +82,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
{
ref: nodeRef,
onChange( isFocused ) {
if ( isFocused && hasReducedUI ) {
if ( isFocused && isDistractionFree ) {
return;
}
toggleBlockHighlight( blockClientId, isFocused );
Expand Down Expand Up @@ -132,9 +132,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
) }
<BlockMover
clientIds={ blockClientIds }
hideDragHandle={
hideDragHandle || hasReducedUI
}
hideDragHandle={ hideDragHandle }
/>
</ToolbarGroup>
) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ function InsertionPointPopover( {
nextClientId,
rootClientId,
isInserterShown,
isDistractionFree,
isNavigationMode,
} = useSelect( ( select ) => {
const {
getBlockOrder,
Expand All @@ -41,6 +43,8 @@ function InsertionPointPopover( {
isBlockBeingDragged,
getPreviousBlockClientId,
getNextBlockClientId,
getSettings,
isNavigationMode: _isNavigationMode,
} = select( blockEditorStore );
const insertionPoint = getBlockInsertionPoint();
const order = getBlockOrder( insertionPoint.rootClientId );
Expand All @@ -60,13 +64,17 @@ function InsertionPointPopover( {
_nextClientId = getNextBlockClientId( _nextClientId );
}

const settings = getSettings();

return {
previousClientId: _previousClientId,
nextClientId: _nextClientId,
orientation:
getBlockListSettings( insertionPoint.rootClientId )
?.orientation || 'vertical',
rootClientId: insertionPoint.rootClientId,
isNavigationMode: _isNavigationMode(),
isDistractionFree: settings.isDistractionFree,
isInserterShown: insertionPoint?.__unstableWithInserter,
};
}, [] );
Expand Down Expand Up @@ -161,6 +169,10 @@ function InsertionPointPopover( {
},
};

if ( isDistractionFree && ! isNavigationMode ) {
return null;
}

const className = classnames(
'block-editor-block-list__insertion-point',
'is-' + orientation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function selector( select ) {
isMultiSelecting: isMultiSelecting(),
isTyping: isTyping(),
hasFixedToolbar: getSettings().hasFixedToolbar,
isDistractionFree: getSettings().isDistractionFree,
lastClientId: hasMultiSelection()
? getLastMultiSelectedBlockClientId()
: null,
Expand All @@ -46,6 +47,7 @@ function SelectedBlockPopover( {
clientId,
rootClientId,
isEmptyDefaultBlock,
showContents, // we may need to mount an empty popover because we reuse
capturingClientId,
__unstablePopoverSlot,
__unstableContentRef,
Expand All @@ -55,6 +57,7 @@ function SelectedBlockPopover( {
isMultiSelecting,
isTyping,
hasFixedToolbar,
isDistractionFree,
lastClientId,
} = useSelect( selector, [] );
const isInsertionPointVisible = useSelect(
Expand Down Expand Up @@ -94,6 +97,7 @@ function SelectedBlockPopover( {
editorMode === 'edit' &&
! shouldShowContextualToolbar &&
! hasFixedToolbar &&
! isDistractionFree &&
! isEmptyDefaultBlock;

useShortcut(
Expand Down Expand Up @@ -136,7 +140,7 @@ function SelectedBlockPopover( {
resize={ false }
{ ...popoverProps }
>
{ shouldShowContextualToolbar && (
{ shouldShowContextualToolbar && showContents && (
<BlockContextualToolbar
// If the toolbar is being shown because of being forced
// it should focus the toolbar right after the mount.
Expand Down Expand Up @@ -169,6 +173,8 @@ function wrapperSelector( select ) {
getBlockRootClientId,
getBlock,
getBlockParents,
getSettings,
isNavigationMode: _isNavigationMode,
__experimentalGetBlockListSettingsForBlocks,
} = select( blockEditorStore );

Expand All @@ -195,10 +201,14 @@ function wrapperSelector( select ) {
?.__experimentalCaptureToolbars
);

const settings = getSettings();

return {
clientId,
rootClientId: getBlockRootClientId( clientId ),
name,
isDistractionFree: settings.isDistractionFree,
isNavigationMode: _isNavigationMode(),
isEmptyDefaultBlock:
name && isUnmodifiedDefaultBlock( { name, attributes } ),
capturingClientId,
Expand All @@ -221,6 +231,8 @@ export default function WrappedBlockPopover( {
name,
isEmptyDefaultBlock,
capturingClientId,
isDistractionFree,
isNavigationMode,
} = selected;

if ( ! name ) {
Expand All @@ -232,6 +244,7 @@ export default function WrappedBlockPopover( {
clientId={ clientId }
rootClientId={ rootClientId }
isEmptyDefaultBlock={ isEmptyDefaultBlock }
showContents={ ! isDistractionFree || isNavigationMode }
capturingClientId={ capturingClientId }
__unstablePopoverSlot={ __unstablePopoverSlot }
__unstableContentRef={ __unstableContentRef }
Expand Down
43 changes: 31 additions & 12 deletions packages/edit-post/src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { PostSavedState, PostPreviewButton } from '@wordpress/editor';
import { useSelect } from '@wordpress/data';
import { PinnedItems } from '@wordpress/interface';
import { useViewportMatch } from '@wordpress/compose';
import { __unstableMotion as motion } from '@wordpress/components';

/**
* Internal dependencies
Expand All @@ -23,13 +24,12 @@ import MainDashboardButton from './main-dashboard-button';
import { store as editPostStore } from '../../store';
import TemplateTitle from './template-title';

function Header( { setEntitiesSavedStatesCallback } ) {
function Header( { setEntitiesSavedStatesCallback, isDistractionFree } ) {
const {
hasActiveMetaboxes,
isPublishSidebarOpened,
isSaving,
showIconLabels,
hasReducedUI,
} = useSelect(
( select ) => ( {
hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(),
Expand All @@ -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 (
<div className={ classes }>
<MainDashboardButton.Slot>
<FullscreenModeClose showTooltip />
<motion.div
variants={ slideX }
transition={ { type: 'tween', delay: 0.8 } }
>
<FullscreenModeClose showTooltip />
</motion.div>
</MainDashboardButton.Slot>
<div className="edit-post-header__toolbar">
<motion.div
variants={ slideY }
transition={ { type: 'tween', delay: 0.8 } }
className="edit-post-header__toolbar"
>
<HeaderToolbar />
<TemplateTitle />
</div>
<div className="edit-post-header__settings">
</motion.div>
<motion.div
variants={ slideY }
transition={ { type: 'tween', delay: 0.8 } }
className="edit-post-header__settings"
>
{ ! 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
Expand Down Expand Up @@ -93,7 +112,7 @@ function Header( { setEntitiesSavedStatesCallback } ) {
{ showIconLabels && ! isLargeViewport && (
<MoreMenu showIconLabels={ showIconLabels } />
) }
</div>
</motion.div>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const MoreMenu = ( { showIconLabels } ) => {
scope="core/edit-post"
/>
) }
<WritingMenu />
<WritingMenu onClose={ onClose } />
<ModeSwitcher />
<ActionItem.Slot
name="core/edit-post/plugin-more-menu"
Expand Down
44 changes: 44 additions & 0 deletions packages/edit-post/src/components/header/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,47 @@
}
}
}

.is-distraction-free {
.interface-interface-skeleton__header {
border-bottom: none;
}

.edit-post-header {
backdrop-filter: blur(20px) !important;
background-color: rgba(255, 255, 255, 0.9);
border-bottom: 1px solid #e0e0e0;
position: absolute;
width: 100%;


// hide some parts
& > .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;
}

}
Loading

0 comments on commit 1e2d8b0

Please sign in to comment.