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

Site Editor: Add ability to focus on editing a page's content vs the page's template #50857

Merged
merged 49 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
5f3c1b2
Add ability to prevent editing blocks using useBlockEditingMode()
noisysocks May 15, 2023
bcf6949
Make useBlockEditingMode use context
noisysocks May 22, 2023
6ab13d7
Remove rootBlockEditingMode setting
noisysocks May 22, 2023
6426fca
Fix private createRegistrySelector selectors
noisysocks May 22, 2023
bd2f478
Consolidate templateLock=contentOnly logic into getBlockEditingMode
noisysocks May 22, 2023
f00dc25
Hide disabled blocks from List View
noisysocks May 22, 2023
c7e128c
Hide disabled blocks from breadcrumbs
noisysocks May 22, 2023
2a9b9e5
Add doc comments
noisysocks May 22, 2023
692cd76
Add unit tests
noisysocks May 23, 2023
8162afe
Use @typedef to document mode param
noisysocks May 23, 2023
52c4df0
Merge remote-tracking branch 'origin/trunk' into try/block-editing-mode
noisysocks May 23, 2023
3d437a4
Restore packages/components/package.json from trunk
noisysocks May 23, 2023
25f3e58
Restore packages/block-library/src/post-title/edit.js from trunk
noisysocks May 23, 2023
f1e1a11
Move BlockListBlockContext out of block.js so that it exists on mobil…
noisysocks May 23, 2023
6bf1ddd
Site Editor: Add ability to focus on editing a page's content vs the …
noisysocks May 23, 2023
727ecd2
Show page information in DocumentActions
noisysocks May 24, 2023
6bd3ab8
Merge remote-tracking branch 'origin/trunk' into add/template-post-co…
noisysocks May 24, 2023
12e8ad4
Implement Content panel
noisysocks May 24, 2023
4489da2
Prevent block overlay on disabled blocks
noisysocks May 24, 2023
fda46cd
Fix Navigation block being selectable
noisysocks May 24, 2023
0443db4
Show 'Page' in breadcrumbs when focused on editing page
noisysocks May 24, 2023
8c1c4a6
Update post title, post featured image, and post content blocks to sa…
noisysocks May 24, 2023
bed91ec
toolbar title styling
SaxonF May 24, 2023
23837de
Remove removePostFromContentBlockLabels for now
noisysocks May 25, 2023
3cd4a17
Fix being able to select text within disabled blocks
noisysocks May 25, 2023
599a4d1
Hide BlockAppender when block is disabled
noisysocks May 25, 2023
5d52359
Fix comments block in non-post templates
noisysocks May 25, 2023
055b7f1
Update template card selector in E2E tests
noisysocks May 25, 2023
79c59bf
Fix 'Add submenu' button in Navigation block
noisysocks May 25, 2023
726c6cc
Merge remote-tracking branch 'origin/trunk' into add/template-post-co…
noisysocks May 25, 2023
89212cd
Remove unhelpful comments
noisysocks May 25, 2023
bdee82a
Remove more unnecessary comments
noisysocks May 25, 2023
0395bf0
Use constant for block types array
noisysocks May 25, 2023
67cf0db
Use BEMish selectors
noisysocks May 25, 2023
50748c2
Be explicit that we're switching away from the page lock
noisysocks May 25, 2023
a468d55
Update removePageFromBlockContext() test
noisysocks May 25, 2023
261d076
Fix post context from appearing in Edit Template preview
noisysocks May 25, 2023
64d0e43
Clear block selection when switching from template focus to page focus
noisysocks May 25, 2023
c860258
Prevent insertion into a disabled block
noisysocks May 25, 2023
c22368a
Don't allow removing and moving children of disabled blocks
noisysocks May 25, 2023
32b5413
Work around @wordpress/data bug by not using createRegistrySelector()…
noisysocks May 26, 2023
9eba206
Fix typo
ramonjd May 31, 2023
245a0bb
Fix select() mock
noisysocks Jun 1, 2023
97e8f23
Fix block-editor selector tests
noisysocks Jun 1, 2023
46c4074
Merge remote-tracking branch 'origin/trunk' into add/template-post-co…
noisysocks Jun 1, 2023
cd90a63
Revert block-editor changes
noisysocks Jun 1, 2023
7e64fa5
Merge remote-tracking branch 'origin/trunk' into add/template-post-co…
noisysocks Jun 2, 2023
fa8133b
Improve useDisableNonContentBlocks performance
noisysocks Jun 2, 2023
f3fc2ca
Fix performance tests
noisysocks Jun 2, 2023
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
36 changes: 36 additions & 0 deletions docs/reference-guides/data/data-core-edit-site.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ _Returns_

- `Object`: Settings.

### hasPageContentLock

Whether or not the editor is locked so that only page content can be edited.

_Parameters_

- _state_ `Object`: Global application state.

_Returns_

- `boolean`: Whether or not the editor is locked.

### isFeatureActive

> **Deprecated**
Expand Down Expand Up @@ -174,6 +186,22 @@ _Returns_

> **Deprecated**

### isPage

Whether or not the editor has a page loaded into it.

_Related_

- setPage

_Parameters_

- _state_ `Object`: Global application state.

_Returns_

- `boolean`: Whether or not the editor has a page loaded into it.

### isSaveViewOpened

Returns the current opened/closed state of the save panel.
Expand Down Expand Up @@ -252,6 +280,14 @@ _Returns_

- `number`: The resolved template ID for the page route.

### setHasPageContentLock

Sets whether or not the editor is locked so that only page content can be edited.

_Parameters_

- _hasPageContentLock_ `boolean`: True to enable lock, false to disable.

### setHomeTemplateId

> **Deprecated**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getDefaultBlockName } from '@wordpress/blocks';
import DefaultBlockAppender from '../default-block-appender';
import ButtonBlockAppender from '../button-block-appender';
import { store as blockEditorStore } from '../../store';
import { unlock } from '../../lock-unlock';

function DefaultAppender( { rootClientId } ) {
const canInsertDefaultBlock = useSelect( ( select ) =>
Expand Down Expand Up @@ -46,13 +47,15 @@ function useAppender( rootClientId, CustomAppender ) {
getTemplateLock,
getSelectedBlockClientId,
__unstableGetEditorMode,
} = select( blockEditorStore );
getBlockEditingMode,
} = unlock( select( blockEditorStore ) );

const selectedBlockClientId = getSelectedBlockClientId();

return {
hideInserter:
!! getTemplateLock( rootClientId ) ||
getBlockEditingMode( rootClientId ) === 'disabled' ||
__unstableGetEditorMode() === 'zoom-out',
isParentSelected:
rootClientId === selectedBlockClientId ||
Expand Down
20 changes: 8 additions & 12 deletions packages/block-editor/src/components/block-list/content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,6 @@
padding: 0;
}

.block-editor-block-list__layout,
.block-editor-block-list__block {
pointer-events: initial;

&.is-editing-disabled {
pointer-events: none;
}
}

.block-editor-block-list__layout .block-editor-block-list__block {
// With `position: static`, Safari marks a full-width selection rectangle, including margins.
// With `position: relative`, Safari marks an inline selection rectangle, similar to that of
Expand All @@ -178,12 +169,17 @@
// We choose relative, as that matches the multi-selection, which is limited to the block footprint.
position: relative;

// Re-enable text-selection on editable blocks.
user-select: text;

// Break long strings of text without spaces so they don't overflow the block.
overflow-wrap: break-word;

pointer-events: auto;
user-select: text;

&.is-editing-disabled {
pointer-events: none;
user-select: none;
}

.reusable-block-edit-panel * {
z-index: z-index(".block-editor-block-list__block .reusable-block-edit-panel *");
}
Expand Down
58 changes: 28 additions & 30 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import createSelector from 'rememo';
/**
* WordPress dependencies
*/
import { createRegistrySelector } from '@wordpress/data';
import { select } from '@wordpress/data';
import { store as blocksStore } from '@wordpress/blocks';

/**
Expand Down Expand Up @@ -71,35 +71,33 @@ export function getLastInsertedBlocksClientIds( state ) {
* @return {BlockEditingMode} The block editing mode. One of `'disabled'`,
* `'contentOnly'`, or `'default'`.
*/
export const getBlockEditingMode = createRegistrySelector(
( select ) =>
( state, clientId = '' ) => {
const explicitEditingMode = getExplcitBlockEditingMode(
state,
clientId
);
const rootClientId = getBlockRootClientId( state, clientId );
const templateLock = getTemplateLock( state, rootClientId );
const name = getBlockName( state, clientId );
const isContent =
select( blocksStore ).__experimentalHasContentRoleAttribute(
name
);
if (
explicitEditingMode === 'disabled' ||
( templateLock === 'contentOnly' && ! isContent )
) {
return 'disabled';
}
if (
explicitEditingMode === 'contentOnly' ||
( templateLock === 'contentOnly' && isContent )
) {
return 'contentOnly';
}
return 'default';
}
);
export const getBlockEditingMode = ( state, clientId = '' ) => {
const explicitEditingMode = getExplcitBlockEditingMode( state, clientId );
ramonjd marked this conversation as resolved.
Show resolved Hide resolved
const rootClientId = getBlockRootClientId( state, clientId );
const templateLock = getTemplateLock( state, rootClientId );
const name = getBlockName( state, clientId );
// TODO: Terrible hack! We're calling the global select() function here
// instead of using createRegistrySelector(). The problem with using
// createRegistrySelector() is that then the public block-editor selectors
// (e.g. canInsertBlockTypeUnmemoized) can't call this private block-editor
// selector due to a bug in @wordpress/data. See
// https://github.com/WordPress/gutenberg/pull/50985.
const isContent =
select( blocksStore ).__experimentalHasContentRoleAttribute( name );
if (
explicitEditingMode === 'disabled' ||
( templateLock === 'contentOnly' && ! isContent )
) {
return 'disabled';
}
if (
explicitEditingMode === 'contentOnly' ||
( templateLock === 'contentOnly' && isContent )
) {
return 'contentOnly';
}
return 'default';
};

const getExplcitBlockEditingMode = createSelector(
( state, clientId = '' ) => {
Expand Down
50 changes: 30 additions & 20 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import deprecated from '@wordpress/deprecated';
*/
import { mapRichTextSettings } from './utils';
import { orderBy } from '../utils/sorting';
import { getBlockEditingMode } from './private-selectors';

/**
* A block selection object.
Expand Down Expand Up @@ -1539,6 +1540,10 @@ const canInsertBlockTypeUnmemoized = (
return false;
}

if ( getBlockEditingMode( state, rootClientId ) === 'disabled' ) {
return false;
}

const parentBlockListSettings = getBlockListSettings( state, rootClientId );

// The parent block doesn't have settings indicating it doesn't support
Expand Down Expand Up @@ -1663,21 +1668,19 @@ export function canInsertBlocks( state, clientIds, rootClientId = null ) {
*/
export function canRemoveBlock( state, clientId, rootClientId = null ) {
const attributes = getBlockAttributes( state, clientId );

// attributes can be null if the block is already deleted.
if ( attributes === null ) {
return true;
}

const { lock } = attributes;
const parentIsLocked = !! getTemplateLock( state, rootClientId );
// If we don't have a lock on the blockType level, we defer to the parent templateLock.
if ( lock === undefined || lock?.remove === undefined ) {
return ! parentIsLocked;
if ( attributes.lock?.remove ) {
return false;
}

// When remove is true, it means we cannot remove it.
return ! lock?.remove;
if ( getTemplateLock( state, rootClientId ) ) {
return false;
}
if ( getBlockEditingMode( state, rootClientId ) === 'disabled' ) {
return false;
}
return true;
noisysocks marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down Expand Up @@ -1709,16 +1712,16 @@ export function canMoveBlock( state, clientId, rootClientId = null ) {
if ( attributes === null ) {
return;
}

const { lock } = attributes;
const parentIsLocked = getTemplateLock( state, rootClientId ) === 'all';
// If we don't have a lock on the blockType level, we defer to the parent templateLock.
if ( lock === undefined || lock?.move === undefined ) {
return ! parentIsLocked;
if ( attributes.lock?.move ) {
return false;
}

// When move is true, it means we cannot move it.
return ! lock?.move;
if ( getTemplateLock( state, rootClientId ) === 'all' ) {
return false;
}
if ( getBlockEditingMode( state, rootClientId ) === 'disabled' ) {
return false;
}
return true;
}

/**
Expand Down Expand Up @@ -2812,6 +2815,13 @@ export function __unstableGetTemporarilyEditingAsBlocks( state ) {
}

export function __unstableHasActiveBlockOverlayActive( state, clientId ) {
// Prevent overlay on disabled blocks. It's redundant since disabled blocks
// can't be selected, and prevents non-disabled nested blocks from being
// selected.
if ( getBlockEditingMode( state, clientId ) === 'disabled' ) {
return false;
}

// If the block editing is locked, the block overlay is always active.
if ( ! canEditBlock( state, clientId ) ) {
return true;
Expand Down
26 changes: 14 additions & 12 deletions packages/block-library/src/navigation/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -508,20 +508,22 @@ body.editor-styles-wrapper .wp-block-navigation__responsive-container.is-menu-op
// so focus is applied naturally on the block container.
// It's important the right container has focus, otherwise you can't press
// "Delete" to remove the block.
.wp-block-navigation__responsive-container,
.wp-block-navigation__responsive-close {
@include break-small() {
pointer-events: none;

.wp-block-navigation__responsive-container-close,
.block-editor-block-list__layout * {
pointer-events: all;
.wp-block-navigation:not(.is-editing-disabled) {
.wp-block-navigation__responsive-container,
.wp-block-navigation__responsive-close {
@include break-small() {
pointer-events: none;

.wp-block-navigation__responsive-container-close,
.block-editor-block-list__layout * {
pointer-events: all;
}
}
}

// Page List items should remain inert.
.wp-block-pages-list__item__link {
pointer-events: none;
// Page List items should remain inert.
.wp-block-pages-list__item__link {
pointer-events: none;
}
}
}

Expand Down
35 changes: 21 additions & 14 deletions packages/block-library/src/post-title/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
InspectorControls,
useBlockProps,
PlainText,
privateApis as blockEditorPrivateApis,
} from '@wordpress/block-editor';
import { ToggleControl, TextControl, PanelBody } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
Expand All @@ -23,6 +24,9 @@ import { useEntityProp } from '@wordpress/core-data';
*/
import HeadingLevelDropdown from '../heading/heading-level-dropdown';
import { useCanEditEntity } from '../utils/hooks';
import { unlock } from '../private-apis';

const { useBlockEditingMode } = unlock( blockEditorPrivateApis );

export default function PostTitleEdit( {
attributes: { level, textAlign, isLink, rel, linkTarget },
Expand Down Expand Up @@ -58,6 +62,7 @@ export default function PostTitleEdit( {
[ `has-text-align-${ textAlign }` ]: textAlign,
} ),
} );
const blockEditingMode = useBlockEditingMode();

let titleElement = (
<TagName { ...blockProps }>{ __( 'Post Title' ) }</TagName>
Expand Down Expand Up @@ -114,20 +119,22 @@ export default function PostTitleEdit( {

return (
<>
<BlockControls group="block">
<HeadingLevelDropdown
selectedLevel={ level }
onChange={ ( newLevel ) =>
setAttributes( { level: newLevel } )
}
/>
<AlignmentControl
value={ textAlign }
onChange={ ( nextAlign ) => {
setAttributes( { textAlign: nextAlign } );
} }
/>
</BlockControls>
{ blockEditingMode === 'default' && (
<BlockControls group="block">
Copy link
Member

Choose a reason for hiding this comment

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

Screenshot 2023-05-31 at 3 32 14 pm

The black dot is a collapsed border style, and appears on all page blocks that are contentOnly, e.g., feature image block as well.

There's a permanent border on the following element (I've added border:0 inline to remove it via the console)

<div id="id-0f1fdc" role="toolbar" aria-orientation="horizontal" aria-label="Block tools" class="components-accessible-toolbar block-editor-block-contextual-toolbar" style="
    border: 0;
"><div class="block-editor-block-toolbar"><div></div></div></div>

This element is rendered by <BlockContextualToolbar /> (block-contextual-toolbar.js). The offending CSS rule for .block-editor-block-contextual-toolbar is in style.scss.

The element is always rendered, even when the slots are empty.

I'm not sure what the best approach is. Checking via useSlotFills() whether the slot is, indeed filled? Would we have to loop through all groups.js?

I'm also guessing the value of blockEditingMode in might not be useful to since the toolbar can show fordefaultandcontentOnly. In this case the site title block has a value of contentOnly`, but the slots are not filled.

Just dumping my brain here in case it helps... :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for digging into this. I'm also not sure how best to fix it. It's a shame we can't use the :empty pseudo selector in CSS because the toolbar technically isn't empty (there's a <div />). Checking if there's fills via useSlotFills() is probably the best bet like you say.

At any rate I'm going to leave fix this for a follow-up PR. (It's noted in the PR description.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we do something like :has( > div:empty:only-child)? Fine to address as a follow-up though 😅

Copy link
Member Author

Choose a reason for hiding this comment

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

:has doesn't work in Firefox 😭 I'll pick your brain about this next week.

<HeadingLevelDropdown
selectedLevel={ level }
onChange={ ( newLevel ) =>
setAttributes( { level: newLevel } )
}
/>
<AlignmentControl
value={ textAlign }
onChange={ ( nextAlign ) => {
setAttributes( { textAlign: nextAlign } );
} }
/>
</BlockControls>
) }
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm still able to edit/interact with block toolbars in the header when in content editing mode, though the toolbars no longer show the block type:

Screenshot 2023-05-25 at 1 27 28 pm Screenshot 2023-05-25 at 1 27 57 pm

Copy link
Member Author

Choose a reason for hiding this comment

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

Huh, I don't see that... what steps did you take?

Copy link
Contributor

Choose a reason for hiding this comment

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

I can too - site title and paragraphs in the header and footer seem to be editable. Not sure I did anything special.

I also noticed that when switching from editing the template back to editing the page content, the block you have selected might be part of the template, but it remains selected and has a toolbar.

Copy link
Contributor

@andrewserong andrewserong May 25, 2023

Choose a reason for hiding this comment

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

I noticed the same. This PR is otherwise testing quite nicely for me, though!

Here's a screengrab in case it helps:

2023-05-25.16.22.38.mp4

Copy link
Member Author

@noisysocks noisysocks May 25, 2023

Choose a reason for hiding this comment

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

Do you have the latest changes pulled? There was a bug where you could select a locked block by double clicking or dragging that should be fixed in 3cd4a17.

Copy link
Contributor

@andrewserong andrewserong May 25, 2023

Choose a reason for hiding this comment

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

Do you have the latest changes pulled?

Yes, just tried re-pulling, and my environment says it's up to date, and I re-ran npm run dev. In the screengrab, I'm single-clicking the Site Title block in the header, but I can also reproduce by clicking the Site Title or Paragraph blocks in the footer, too.

Very weird — I can see the pointer-events: none rule should be applying, but I was still able to select the block 🤔

image

Copy link
Contributor

Choose a reason for hiding this comment

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

I have latest changes too.

Copy link
Member Author

Choose a reason for hiding this comment

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

Are you using TT3?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep!

Copy link
Member Author

Choose a reason for hiding this comment

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

Aha, looks like it only happens in Chrome. I'll investigate tomorrow.

<InspectorControls>
<PanelBody title={ __( 'Settings' ) }>
<ToggleControl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ async function getActiveTabLabel() {
async function getTemplateCard() {
return {
title: await page.$eval(
'.edit-site-template-card__title',
'.edit-site-sidebar-card__title',
( element ) => element.innerText
),
description: await page.$eval(
'.edit-site-template-card__description',
'.edit-site-sidebar-card__description',
( element ) => element.innerText
),
};
Expand Down
Loading