Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Focus Mode: Hide Block Outlines #9394

Merged
merged 16 commits into from
Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,30 @@ import { withSelect, withDispatch } from '@wordpress/data';
/**
* WordPress Dependencies
*/
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { MenuItem } from '@wordpress/components';
import { ifViewportMatches } from '@wordpress/viewport';

function FixedToolbarToggle( { onToggle, isActive } ) {
function FeatureToggle( { onToggle, isActive, label } ) {
return (
<MenuItem
icon={ isActive && 'yes' }
isSelected={ isActive }
onClick={ onToggle }
role="menuitemcheckbox"
>
{ __( 'Fix Toolbar to Top' ) }
{ label }
</MenuItem>
);
}

export default compose( [
withSelect( ( select ) => ( {
isActive: select( 'core/edit-post' ).isFeatureActive( 'fixedToolbar' ),
withSelect( ( select, { feature } ) => ( {
isActive: select( 'core/edit-post' ).isFeatureActive( feature ),
} ) ),
withDispatch( ( dispatch, ownProps ) => ( {
onToggle() {
dispatch( 'core/edit-post' ).toggleFeature( 'fixedToolbar' );
dispatch( 'core/edit-post' ).toggleFeature( ownProps.feature );
ownProps.onToggle();
},
} ) ),
ifViewportMatches( 'medium' ),
] )( FixedToolbarToggle );
] )( FeatureToggle );
11 changes: 3 additions & 8 deletions edit-post/components/header/more-menu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import { Fragment } from '@wordpress/element';
*/
import './style.scss';
import ModeSwitcher from '../mode-switcher';
import FixedToolbarToggle from '../fixed-toolbar-toggle';
import PluginMoreMenuGroup from '../plugins-more-menu-group';
import TipsToggle from '../tips-toggle';
import KeyboardShortcutsHelpMenuItem from '../keyboard-shortcuts-help-menu-item';
import WritingMenu from '../writing-menu';

const MoreMenu = () => (
<Dropdown
Expand All @@ -30,19 +30,14 @@ const MoreMenu = () => (
) }
renderContent={ ( { onClose } ) => (
<Fragment>
<WritingMenu onClose={ onClose } />
<ModeSwitcher onSelect={ onClose } />
<MenuGroup
label={ __( 'Settings' ) }
filterName="editPost.MoreMenu.settings"
>
<FixedToolbarToggle onToggle={ onClose } />
<TipsToggle onToggle={ onClose } />
</MenuGroup>
<PluginMoreMenuGroup.Slot fillProps={ { onClose } } />
<MenuGroup
label={ __( 'Tools' ) }
filterName="editPost.MoreMenu.tools"
>
<TipsToggle onToggle={ onClose } />
<KeyboardShortcutsHelpMenuItem onSelect={ onClose } />
</MenuGroup>
</Fragment>
Expand Down
25 changes: 25 additions & 0 deletions edit-post/components/header/writing-menu/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* WordPress Dependencies
*/
import { MenuGroup } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { ifViewportMatches } from '@wordpress/viewport';

/**
* Internal dependencies
*/
import FeatureToggle from '../feature-toggle';

function WritingMenu( { onClose } ) {
return (
<MenuGroup
label={ __( 'Writing' ) }
filterName="editPost.MoreMenu.writing"
Copy link
Member

@gziolo gziolo Aug 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this filter, it shouldn't be used in the long run. We should rather offer some fill if we want to make it possible to add an item to this group.

I can take care of it in the follow-up PR, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to ping you about it :)

>
<FeatureToggle feature="fixedToolbar" label={ __( 'Unified Toolbar' ) } onToggle={ onClose } />
<FeatureToggle feature="focusMode" label={ __( 'Spotlight Mode' ) } onToggle={ onClose } />
</MenuGroup>
);
}

export default ifViewportMatches( 'medium' )( WritingMenu );
18 changes: 16 additions & 2 deletions edit-post/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,32 @@ import { StrictMode } from '@wordpress/element';
*/
import Layout from './components/layout';

function Editor( { settings, hasFixedToolbar, post, overridePost, onError, ...props } ) {
function Editor( {
settings,
hasFixedToolbar,
focusMode,
post,
overridePost,
onError,
...props
} ) {
if ( ! post ) {
return null;
}

const editorSettings = {
...settings,
hasFixedToolbar,
focusMode,
};

return (
<StrictMode>
<EditorProvider settings={ editorSettings } post={ { ...post, ...overridePost } } { ...props }>
<EditorProvider
settings={ editorSettings }
post={ { ...post, ...overridePost } }
{ ...props }
>
<ErrorBoundary onError={ onError }>
<Layout />
</ErrorBoundary>
Expand All @@ -33,5 +46,6 @@ function Editor( { settings, hasFixedToolbar, post, overridePost, onError, ...pr

export default withSelect( ( select, { postId, postType } ) => ( {
hasFixedToolbar: select( 'core/edit-post' ).isFeatureActive( 'fixedToolbar' ),
focusMode: select( 'core/edit-post' ).isFeatureActive( 'focusMode' ),
post: select( 'core' ).getEntityRecord( 'postType', postType, postId ),
} ) )( Editor );
32 changes: 19 additions & 13 deletions packages/editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ export class BlockListBlock extends Component {
block,
order,
mode,
isFocusMode,
hasFixedToolbar,
isLocked,
isFirst,
Expand All @@ -367,11 +368,11 @@ export class BlockListBlock extends Component {
isTypingWithinBlock,
isMultiSelecting,
hoverArea,
isLargeViewport,
isEmptyDefaultBlock,
isMovable,
isPreviousBlockADefaultEmptyBlock,
hasSelectedInnerBlock,
isParentOfSelectedBlock,
} = this.props;
const isHovered = this.state.isHovered && ! isMultiSelecting;
const { name: blockName, isValid } = block;
Expand All @@ -385,13 +386,14 @@ export class BlockListBlock extends Component {
// Empty paragraph blocks should always show up as unselected.
const showEmptyBlockSideInserter = ( isSelected || isHovered ) && isEmptyDefaultBlock;
const showSideInserter = ( isSelected || isHovered ) && isEmptyDefaultBlock;
const shouldAppearSelected = ! showSideInserter && isSelected && ! isTypingWithinBlock;
const shouldAppearSelectedParent = ! showSideInserter && hasSelectedInnerBlock && ! isTypingWithinBlock;
const shouldAppearSelected = ! isFocusMode && ! hasFixedToolbar && ! showSideInserter && isSelected && ! isTypingWithinBlock;
const shouldAppearSelectedParent = ! isFocusMode && ! hasFixedToolbar && ! showSideInserter && hasSelectedInnerBlock && ! isTypingWithinBlock;
const shouldAppearHovered = ! isFocusMode && ! hasFixedToolbar && isHovered && ! isEmptyDefaultBlock;
// We render block movers and block settings to keep them tabbale even if hidden
const shouldRenderMovers = ( isSelected || hoverArea === 'left' ) && ! showEmptyBlockSideInserter && ! isMultiSelecting && ! isPartOfMultiSelection && ! isTypingWithinBlock;
const shouldRenderMovers = ! isFocusMode && ( isSelected || hoverArea === 'left' ) && ! showEmptyBlockSideInserter && ! isMultiSelecting && ! isPartOfMultiSelection && ! isTypingWithinBlock;
const shouldRenderBlockSettings = ( isSelected || hoverArea === 'right' ) && ! isMultiSelecting && ! isPartOfMultiSelection;
const shouldShowBreadcrumb = isHovered && ! isEmptyDefaultBlock;
const shouldShowContextualToolbar = ! showSideInserter && ( ( isSelected && ! isTypingWithinBlock && isValid ) || isFirstMultiSelected ) && ( ! hasFixedToolbar || ! isLargeViewport );
const shouldShowBreadcrumb = ! isFocusMode && isHovered && ! isEmptyDefaultBlock;
const shouldShowContextualToolbar = ! hasFixedToolbar && ! showSideInserter && ( ( isSelected && ! isTypingWithinBlock && isValid ) || isFirstMultiSelected );
const shouldShowMobileToolbar = shouldAppearSelected;
const { error, dragging } = this.state;

Expand All @@ -407,10 +409,12 @@ export class BlockListBlock extends Component {
'is-selected': shouldAppearSelected,
'is-multi-selected': isPartOfMultiSelection,
'is-selected-parent': shouldAppearSelectedParent,
'is-hovered': isHovered && ! isEmptyDefaultBlock,
'is-hovered': shouldAppearHovered,
'is-reusable': isReusableBlock( blockType ),
'is-hidden': dragging,
'is-typing': isTypingWithinBlock,
'is-focused': isFocusMode && ( isSelected || isParentOfSelectedBlock ),
'is-focus-mode': isFocusMode,
} );

const { onReplace } = this.props;
Expand Down Expand Up @@ -584,7 +588,7 @@ export class BlockListBlock extends Component {
}
}

const applyWithSelect = withSelect( ( select, { clientId, rootClientId } ) => {
const applyWithSelect = withSelect( ( select, { clientId, rootClientId, isLargeViewport } ) => {
const {
isBlockSelected,
getPreviousBlockClientId,
Expand All @@ -605,19 +609,19 @@ const applyWithSelect = withSelect( ( select, { clientId, rootClientId } ) => {
getTemplateLock,
} = select( 'core/editor' );
const isSelected = isBlockSelected( clientId );
const isParentOfSelectedBlock = hasSelectedInnerBlock( clientId );
const { hasFixedToolbar } = getEditorSettings();
const { hasFixedToolbar, focusMode } = getEditorSettings();
const block = getBlock( clientId );
const previousBlockClientId = getPreviousBlockClientId( clientId );
const previousBlock = getBlock( previousBlockClientId );
const templateLock = getTemplateLock( rootClientId );
const isParentOfSelectedBlock = hasSelectedInnerBlock( clientId, true );

return {
nextBlockClientId: getNextBlockClientId( clientId ),
isPartOfMultiSelection: isBlockMultiSelected( clientId ) || isAncestorMultiSelected( clientId ),
isFirstMultiSelected: isFirstMultiSelectedBlock( clientId ),
isMultiSelecting: isMultiSelecting(),
hasSelectedInnerBlock: isParentOfSelectedBlock,
hasSelectedInnerBlock: hasSelectedInnerBlock( clientId, false ),
// We only care about this prop when the block is selected
// Thus to avoid unnecessary rerenders we avoid updating the prop if the block is not selected.
isTypingWithinBlock: ( isSelected || isParentOfSelectedBlock ) && isTyping(),
Expand All @@ -630,10 +634,12 @@ const applyWithSelect = withSelect( ( select, { clientId, rootClientId } ) => {
isPreviousBlockADefaultEmptyBlock: previousBlock && isUnmodifiedDefaultBlock( previousBlock ),
isMovable: 'all' !== templateLock,
isLocked: !! templateLock,
isFocusMode: focusMode && isLargeViewport,
hasFixedToolbar: hasFixedToolbar && isLargeViewport,
previousBlockClientId,
block,
isSelected,
hasFixedToolbar,
isParentOfSelectedBlock,
};
} );

Expand Down Expand Up @@ -689,9 +695,9 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps ) => {
} );

export default compose(
withViewportMatch( { isLargeViewport: 'medium' } ),
applyWithSelect,
applyWithDispatch,
withViewportMatch( { isLargeViewport: 'medium' } ),
withFilters( 'editor.BlockListBlock' ),
withHoverAreas,
)( BlockListBlock );
14 changes: 11 additions & 3 deletions packages/editor/src/components/block-list/breadcrumb.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
Expand Down Expand Up @@ -48,10 +53,12 @@ export class BlockBreadcrumb extends Component {
}

render() {
const { clientId, rootClientId } = this.props;
const { clientId, rootClientId, isLight } = this.props;

return (
<div className={ 'editor-block-list__breadcrumb' }>
<div className={ classnames( 'editor-block-list__breadcrumb', {
'is-light': isLight,
} ) }>
<Toolbar>
{ rootClientId && (
<Fragment>
Expand All @@ -68,11 +75,12 @@ export class BlockBreadcrumb extends Component {

export default compose( [
withSelect( ( select, ownProps ) => {
const { getBlockRootClientId } = select( 'core/editor' );
const { getBlockRootClientId, getEditorSettings } = select( 'core/editor' );
const { clientId } = ownProps;

return {
rootClientId: getBlockRootClientId( clientId ),
isLight: getEditorSettings().hasFixedToolbar,
};
} ),
] )( BlockBreadcrumb );
20 changes: 19 additions & 1 deletion packages/editor/src/components/block-list/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@
.editor-block-list__block-edit .reusable-block-edit-panel * {
z-index: z-index(".editor-block-list__block-edit .reusable-block-edit-panel *");
}

&.is-focus-mode:not(.is-multi-selected) {
opacity: 0.5;
transition: opacity 0.1s linear;

&:not(.is-focused) .editor-block-list__block,
&.is-focused {
opacity: 1;
}
}
}


Expand Down Expand Up @@ -852,7 +862,6 @@
.components-toolbar {
border-top: none;
border-bottom: none;

}

@include break-small() {
Expand Down Expand Up @@ -897,6 +906,10 @@
}
}

.editor-block-list__block.is-focus-mode > .editor-block-contextual-toolbar {
margin-left: -$block-side-ui-width;
}

// Enable toolbar footprint collapsing
.editor-block-contextual-toolbar {
// Position the contextual toolbar above the block.
Expand Down Expand Up @@ -1008,6 +1021,11 @@
@include fade_in(60ms, 0.5s);
}
}

&.is-light .components-toolbar {
background: rgba($white, 0.5);
color: $dark-gray-700;
}
}

.editor-block-list__descendant-arrow::before {
Expand Down
1 change: 0 additions & 1 deletion packages/editor/src/components/post-permalink/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

// Use opacity to work in various editor styles.
border: $border-width solid $dark-opacity-light-500;
border-bottom: none;
background-clip: padding-box;

// Put toolbar snugly to edge on mobile.
Expand Down
13 changes: 10 additions & 3 deletions packages/editor/src/components/post-title/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,14 @@ class PostTitle extends Component {
}

render() {
const { title, placeholder, instanceId, isPostTypeViewable } = this.props;
const { title, placeholder, instanceId, isPostTypeViewable, isFocusMode, hasFixedToolbar } = this.props;
const { isSelected } = this.state;
const className = classnames( 'editor-post-title__block', { 'is-selected': isSelected } );
const className = classnames( 'editor-post-title__block', {
'is-selected': isSelected,
'is-focus-mode': isFocusMode,
'has-fixed-toolbar': hasFixedToolbar,
'is-focused': isFocusMode && isSelected,
} );
const decodedPlaceholder = decodeEntities( placeholder );

return (
Expand Down Expand Up @@ -129,12 +134,14 @@ const applyWithSelect = withSelect( ( select ) => {
const { getEditedPostAttribute, getEditorSettings } = select( 'core/editor' );
const { getPostType } = select( 'core' );
const postType = getPostType( getEditedPostAttribute( 'type' ) );
const { titlePlaceholder } = getEditorSettings();
const { titlePlaceholder, focusMode, hasFixedToolbar } = getEditorSettings();

return {
title: getEditedPostAttribute( 'title' ),
isPostTypeViewable: get( postType, [ 'viewable' ], false ),
placeholder: titlePlaceholder,
isFocusMode: focusMode,
hasFixedToolbar,
};
} );

Expand Down
Loading