Skip to content

Commit

Permalink
Flash editable block outlines instead of always showing them (#58159)
Browse files Browse the repository at this point in the history
* Flash editable block outlines instead of always showing them

Updates the editable block outlines that appear within content-locked
containers (added in #57901) to appear and then fade out after 3s when:

- The page loads; or
- The user clicks on the content-locked container.

This is done via a private useFlashEditableBlocks() hook attached to the
container.

* Don't show outlines when site editor is in view mode

* Prevent outlines from flashing when selecting an editable inner block

* Fix React warning

* Avoid multiple calls to getBlockEditingMode()

* Flash editable outlines on template patterns with templateLock = 'contentOnly'

* Reduce fade out delay
  • Loading branch information
noisysocks committed Jan 31, 2024
1 parent f2d2a81 commit 24a2cb7
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 63 deletions.
15 changes: 11 additions & 4 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,6 @@ function BlockListBlockProvider( props ) {
isBlockBeingDragged,
hasBlockMovingClientId,
canInsertBlockType,
getBlockRootClientId,
__unstableHasActiveBlockOverlayActive,
__unstableGetEditorMode,
getSelectedBlocksInitialCaretPosition,
Expand All @@ -547,7 +546,6 @@ function BlockListBlockProvider( props ) {
getActiveBlockVariation,
} = select( blocksStore );
const _isSelected = isBlockSelected( clientId );
const templateLock = getTemplateLock( rootClientId );
const canRemove = canRemoveBlock( clientId, rootClientId );
const canMove = canMoveBlock( clientId, rootClientId );
const attributes = getBlockAttributes( clientId );
Expand All @@ -565,10 +563,12 @@ function BlockListBlockProvider( props ) {
const hasLightBlockWrapper = blockType?.apiVersion > 1;
const movingClientId = hasBlockMovingClientId();
const blockEditingMode = getBlockEditingMode( clientId );

return {
mode: getBlockMode( clientId ),
isSelectionEnabled: isSelectionEnabled(),
isLocked: !! templateLock,
isLocked: !! getTemplateLock( rootClientId ),
templateLock: getTemplateLock( clientId ),
canRemove,
canMove,
blockWithoutAttributes,
Expand Down Expand Up @@ -619,9 +619,12 @@ function BlockListBlockProvider( props ) {
movingClientId &&
canInsertBlockType(
getBlockName( movingClientId ),
getBlockRootClientId( clientId )
rootClientId
),
isEditingDisabled: blockEditingMode === 'disabled',
hasEditableOutline:
blockEditingMode !== 'disabled' &&
getBlockEditingMode( rootClientId ) === 'disabled',
className: hasLightBlockWrapper
? attributes.className
: undefined,
Expand Down Expand Up @@ -665,7 +668,9 @@ function BlockListBlockProvider( props ) {
removeOutline,
isBlockMovingMode,
canInsertMovingBlock,
templateLock,
isEditingDisabled,
hasEditableOutline,
className,
defaultClassName,
} = selectedProps;
Expand Down Expand Up @@ -709,7 +714,9 @@ function BlockListBlockProvider( props ) {
removeOutline,
isBlockMovingMode,
canInsertMovingBlock,
templateLock,
isEditingDisabled,
hasEditableOutline,
isTemporarilyEditingAsBlocks,
defaultClassName,
mayDisplayControls,
Expand Down
51 changes: 23 additions & 28 deletions packages/block-editor/src/components/block-list/content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -300,35 +300,30 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b
}
}

// Indicate which blocks are editable within a locked context.
// 1. User must be hovering an editor with renderingMode = 'template-lock'; or...
.is-template-locked:hover,
// ...a container block.
.block-editor-block-list__block:hover {
// 2. Look for locked blocks; or...
.block-editor-block-list__block.is-editing-disabled,
// ...container blocks that have locked children.
&:has(> .block-editor-block-list__block.is-editing-disabled) {
// 3. Highlight any unlocked children of that locked block.
& > .block-editor-block-list__block:not(.is-editing-disabled):not(.is-selected):not(.has-child-selected) {
&::after {
content: "";
border-style: dotted;
position: absolute;
pointer-events: none;
top: $border-width;
left: $border-width;
right: $border-width;
bottom: $border-width;
border: 1px dotted var(--wp-admin-theme-color);
border-radius: $radius-block-ui - $border-width;
}
@keyframes block-editor-has-editable-outline__fade-out-animation {
from {
border-color: rgba(var(--wp-admin-theme-color--rgb), 1);
}
to {
border-color: rgba(var(--wp-admin-theme-color--rgb), 0);
}
}

&.is-hovered::after {
background: rgba(var(--wp-admin-theme-color--rgb), 0.1);
border: none;
}
}
.is-root-container:not([inert]) .block-editor-block-list__block.has-editable-outline {
&::after {
content: "";
position: absolute;
pointer-events: none;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 1px dotted rgba(var(--wp-admin-theme-color--rgb), 1);
border-radius: $radius-block-ui;
animation: block-editor-has-editable-outline__fade-out-animation 0.3s ease-out;
animation-delay: 1s;
animation-fill-mode: forwards;
@include reduce-motion("animation");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { useEventHandlers } from './use-selected-block-event-handlers';
import { useNavModeExit } from './use-nav-mode-exit';
import { useBlockRefProvider } from './use-block-refs';
import { useIntersectionObserver } from './use-intersection-observer';
import { useFlashEditableBlocks } from '../../use-flash-editable-blocks';

/**
* This hook is used to lightly mark an element as a block element. The element
Expand Down Expand Up @@ -95,8 +96,10 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
isBlockMovingMode,
canInsertMovingBlock,
isEditingDisabled,
hasEditableOutline,
isTemporarilyEditingAsBlocks,
defaultClassName,
templateLock,
} = useContext( PrivateBlockContext );

// translators: %s: Type of block (i.e. Text, Image etc)
Expand All @@ -113,6 +116,10 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
useIntersectionObserver(),
useMovingAnimation( { triggerAnimationOnChange: index, clientId } ),
useDisabled( { isDisabled: ! hasOverlay } ),
useFlashEditableBlocks( {
clientId,
isEnabled: name === 'core/block' || templateLock === 'contentOnly',
} ),
] );

const blockEditContext = useBlockEditContext();
Expand Down Expand Up @@ -152,6 +159,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
'is-block-moving-mode': isBlockMovingMode,
'can-insert-moving-block': canInsertMovingBlock,
'is-editing-disabled': isEditingDisabled,
'has-editable-outline': hasEditableOutline,
'is-content-locked-temporarily-editing-as-blocks':
isTemporarilyEditingAsBlocks,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* WordPress dependencies
*/
import { useRefEffect } from '@wordpress/compose';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import { unlock } from '../../lock-unlock';

export function useFlashEditableBlocks( {
clientId = '',
isEnabled = true,
} = {} ) {
const { getEnabledClientIdsTree } = unlock( useSelect( blockEditorStore ) );

return useRefEffect(
( element ) => {
if ( ! isEnabled ) {
return;
}

const flashEditableBlocks = () => {
getEnabledClientIdsTree( clientId ).forEach(
( { clientId: id } ) => {
const block = element.querySelector(
`[data-block="${ id }"]`
);
if ( ! block ) {
return;
}
block.classList.remove( 'has-editable-outline' );
// Force reflow to trigger the animation.
// eslint-disable-next-line no-unused-expressions
block.offsetWidth;
block.classList.add( 'has-editable-outline' );
}
);
};

const handleClick = ( event ) => {
const shouldFlash =
event.target === element ||
event.target.classList.contains( 'is-root-container' );
if ( ! shouldFlash ) {
return;
}
if ( event.defaultPrevented ) {
return;
}
event.preventDefault();
flashEditableBlocks();
};

element.addEventListener( 'click', handleClick );
return () => element.removeEventListener( 'click', handleClick );
},
[ isEnabled ]
);
}
2 changes: 2 additions & 0 deletions packages/block-editor/src/private-apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
import { usesContextKey } from './components/rich-text/format-edit';
import { ExperimentalBlockCanvas } from './components/block-canvas';
import { getDuotoneFilter } from './components/duotone/utils';
import { useFlashEditableBlocks } from './components/use-flash-editable-blocks';

/**
* Private @wordpress/block-editor APIs.
Expand Down Expand Up @@ -52,4 +53,5 @@ lock( privateApis, {
ReusableBlocksRenameHint,
useReusableBlocksRenameHint,
usesContextKey,
useFlashEditableBlocks,
} );
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,18 @@ import { store as editorStore } from '../../store';
* editor iframe canvas.
*/
export default function EditTemplateBlocksNotification( { contentRef } ) {
const { renderingMode, getPostLinkProps, templateId } = useSelect(
( select ) => {
const {
getRenderingMode,
getEditorSettings,
getCurrentTemplateId,
} = select( editorStore );
return {
renderingMode: getRenderingMode(),
getPostLinkProps: getEditorSettings().getPostLinkProps,
templateId: getCurrentTemplateId(),
};
},
[]
);
const editTemplate = getPostLinkProps
? getPostLinkProps( {
postId: templateId,
postType: 'wp_template',
} )
: {};
const editTemplate = useSelect( ( select ) => {
const { getEditorSettings, getCurrentTemplateId } =
select( editorStore );
const { getPostLinkProps } = getEditorSettings();
return getPostLinkProps
? getPostLinkProps( {
postId: getCurrentTemplateId(),
postType: 'wp_template',
} )
: {};
}, [] );

const { getNotices } = useSelect( noticesStore );

const { createInfoNotice, removeNotice } = useDispatch( noticesStore );
Expand All @@ -58,18 +49,17 @@ export default function EditTemplateBlocksNotification( { contentRef } ) {

useEffect( () => {
const handleClick = async ( event ) => {
if ( renderingMode !== 'template-locked' ) {
return;
}
if ( ! event.target.classList.contains( 'is-root-container' ) ) {
return;
}

const isNoticeAlreadyShowing = getNotices().some(
( notice ) => notice.id === lastNoticeId.current
);
if ( isNoticeAlreadyShowing ) {
return;
}

const { notice } = await createInfoNotice(
__( 'Edit your template to edit this block.' ),
{
Expand All @@ -87,9 +77,6 @@ export default function EditTemplateBlocksNotification( { contentRef } ) {
};

const handleDblClick = ( event ) => {
if ( renderingMode !== 'template-locked' ) {
return;
}
if ( ! event.target.classList.contains( 'is-root-container' ) ) {
return;
}
Expand All @@ -106,7 +93,7 @@ export default function EditTemplateBlocksNotification( { contentRef } ) {
canvas?.removeEventListener( 'click', handleClick );
canvas?.removeEventListener( 'dblclick', handleDblClick );
};
}, [ lastNoticeId, renderingMode, contentRef.current ] );
}, [ lastNoticeId, contentRef.current ] );

return (
<ConfirmDialog
Expand Down
11 changes: 8 additions & 3 deletions packages/editor/src/components/editor-canvas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const {
useLayoutClasses,
useLayoutStyles,
ExperimentalBlockCanvas: BlockCanvas,
useFlashEditableBlocks,
} = unlock( blockEditorPrivateApis );

const noop = () => {};
Expand Down Expand Up @@ -290,6 +291,9 @@ function EditorCanvas( {
const contentRef = useMergeRefs( [
localRef,
renderingMode === 'post-only' ? typewriterRef : noop,
useFlashEditableBlocks( {
isEnabled: renderingMode === 'template-locked',
} ),
] );

return (
Expand Down Expand Up @@ -364,8 +368,7 @@ function EditorCanvas( {
'is-' + deviceType.toLowerCase() + '-preview',
renderingMode !== 'post-only'
? 'wp-site-blocks'
: `${ blockListLayoutClass } wp-block-post-content`, // Ensure root level blocks receive default/flow blockGap styling rules.
renderingMode !== 'all' && 'is-' + renderingMode
: `${ blockListLayoutClass } wp-block-post-content` // Ensure root level blocks receive default/flow blockGap styling rules.
) }
layout={ blockListLayout }
dropZoneElement={
Expand All @@ -377,7 +380,9 @@ function EditorCanvas( {
}
renderAppender={ renderAppender }
/>
<EditTemplateBlocksNotification contentRef={ localRef } />
{ renderingMode === 'template-locked' && (
<EditTemplateBlocksNotification contentRef={ localRef } />
) }
</RecursionProvider>
{ children }
</BlockCanvas>
Expand Down

0 comments on commit 24a2cb7

Please sign in to comment.