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

Update the block overlay to rely on useDisabled hook #40649

Merged
merged 5 commits into from
May 6, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,7 @@ _Parameters_
- _props_ `Object`: Optional. Props to pass to the element. Must contain the ref if one is defined.
- _options_ `Object`: Options for internal use only.
- _options.\_\_unstableIsHtml_ `boolean`:
- _options.isDisabled_ `boolean`: Whether the block should be disabled.

_Returns_

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,114 +2,27 @@
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { useState, useEffect } from '@wordpress/element';

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

/**
* External dependencies
*/
import classnames from 'classnames';

export default function BlockContentOverlay( {
Copy link
Member

@Mamaduka Mamaduka May 5, 2022

Choose a reason for hiding this comment

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

Should we deprecate this? Directory search return single plugin - https://wpdirectory.net/search/01G29EAZQER3R2XCAGSMB7MRD5

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was never stable in the first place. So I think it's fine to just remove.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(The result in wp-directory is a plugin that show up in all Gutenberg API searches :P I think it's bundling our packages)

clientId,
tagName: TagName = 'div',
wrapperProps,
className,
} ) {
const baseClassName = 'block-editor-block-content-overlay';
const [ isOverlayActive, setIsOverlayActive ] = useState( true );
const [ isHovered, setIsHovered ] = useState( false );

const {
canEdit,
isParentSelected,
hasChildSelected,
isDraggingBlocks,
isParentHighlighted,
} = useSelect(
export default function useBlockOverlayActive( clientId ) {
return useSelect(
( select ) => {
const {
isBlockSelected,
hasSelectedInnerBlock,
isDraggingBlocks: _isDraggingBlocks,
isBlockHighlighted,
canEditBlock,
} = select( blockEditorStore );
return {
canEdit: canEditBlock( clientId ),
isParentSelected: isBlockSelected( clientId ),
hasChildSelected: hasSelectedInnerBlock( clientId, true ),
isDraggingBlocks: _isDraggingBlocks(),
isParentHighlighted: isBlockHighlighted( clientId ),
};

return (
! canEditBlock( clientId ) ||
( ! isBlockSelected( clientId ) &&
! hasSelectedInnerBlock( clientId, true ) )
);
},
[ clientId ]
);

const classes = classnames(
baseClassName,
wrapperProps?.className,
className,
{
'overlay-active': isOverlayActive,
'parent-highlighted': isParentHighlighted,
'is-dragging-blocks': isDraggingBlocks,
}
);

useEffect( () => {
// The overlay is always active when editing is locked.
if ( ! canEdit ) {
setIsOverlayActive( true );
return;
}

// Reenable when blocks are not in use.
if ( ! isParentSelected && ! hasChildSelected && ! isOverlayActive ) {
setIsOverlayActive( true );
}
// Disable if parent selected by another means (such as list view).
// We check hover to ensure the overlay click interaction is not taking place.
// Trying to click the overlay will select the parent block via its 'focusin'
// listener on the wrapper, so if the block is selected while hovered we will
// let the mouseup disable the overlay instead.
if ( isParentSelected && ! isHovered && isOverlayActive ) {
setIsOverlayActive( false );
}
// Ensure overlay is disabled if a child block is selected.
if ( hasChildSelected && isOverlayActive ) {
setIsOverlayActive( false );
}
}, [
isParentSelected,
hasChildSelected,
isOverlayActive,
isHovered,
canEdit,
] );

// Disabled because the overlay div doesn't actually have a role or functionality
// as far as the a11y is concerned. We're just catching the first click so that
// the block can be selected without interacting with its contents.
/* eslint-disable jsx-a11y/no-static-element-interactions */
return (
<TagName
{ ...wrapperProps }
className={ classes }
onMouseEnter={ () => setIsHovered( true ) }
onMouseLeave={ () => setIsHovered( false ) }
onMouseUp={
isOverlayActive && canEdit
? () => setIsOverlayActive( false )
: undefined
}
>
{ wrapperProps?.children }
</TagName>
);
}
/* eslint-enable jsx-a11y/no-static-element-interactions */
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.block-editor-block-content-overlay {
&.overlay-active::before {
&::before {
content: "";
position: absolute;
top: 0;
Expand All @@ -12,17 +12,8 @@
z-index: z-index(".block-editor-block-content-overlay__overlay");
}

&:hover:not(.is-dragging-blocks).overlay-active::before,
&.parent-highlighted.overlay-active::before {
&:hover:not(.is-dragging-blocks)::before {
background: rgba(var(--wp-admin-theme-color--rgb), 0.1);
box-shadow: 0 0 0 $border-width var(--wp-admin-theme-color) inset;
}

&.overlay-active:not(.is-dragging-blocks) * {
pointer-events: none;
}

&.is-dragging-blocks {
box-shadow: 0 0 0 $border-width var(--wp-admin-theme-color);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
__unstableGetBlockProps as getBlockProps,
getBlockType,
} from '@wordpress/blocks';
import { useMergeRefs } from '@wordpress/compose';
import {
useMergeRefs,
__experimentalUseDisabled as useIsDisabled,
} from '@wordpress/compose';
import { useSelect } from '@wordpress/data';
import warning from '@wordpress/warning';

Expand Down Expand Up @@ -54,10 +57,14 @@ const BLOCK_ANIMATION_THRESHOLD = 200;
* the ref if one is defined.
* @param {Object} options Options for internal use only.
* @param {boolean} options.__unstableIsHtml
* @param {boolean} options.isDisabled Whether the block should be disabled.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another approach here would be a options.hasOverlay flag and bundle the call to useBlockOverlay here. I might switch to that as it avoids a lot of duplication.

*
* @return {Object} Props to pass to the element to mark as a block.
*/
export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
export function useBlockProps(
props = {},
{ __unstableIsHtml, isDisabled = false } = {}
) {
const { clientId, className, wrapperProps = {}, isAligned } = useContext(
BlockListBlockContext
);
Expand Down Expand Up @@ -125,6 +132,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
enableAnimation,
triggerAnimationOnChange: index,
} ),
useIsDisabled( { isDisabled: ! isDisabled } ),
] );

const blockEditContext = useBlockEditContext();
Expand Down
2 changes: 1 addition & 1 deletion packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export {
export { default as __experimentalBlockFullHeightAligmentControl } from './block-full-height-alignment-control';
export { default as __experimentalBlockAlignmentMatrixControl } from './block-alignment-matrix-control';
export { default as BlockBreadcrumb } from './block-breadcrumb';
export { default as __experimentalBlockContentOverlay } from './block-content-overlay';
export { default as __experimentalUseBlockOverlayActive } from './block-content-overlay';
export { BlockContextProvider } from './block-context';
export {
default as BlockControls,
Expand Down
79 changes: 38 additions & 41 deletions packages/block-library/src/block/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { __ } from '@wordpress/i18n';
import {
useInnerBlocksProps,
__experimentalUseNoRecursiveRenders as useNoRecursiveRenders,
__experimentalBlockContentOverlay as BlockContentOverlay,
__experimentalUseBlockOverlayActive as useBlockOverlayActive,
InnerBlocks,
BlockControls,
InspectorControls,
Expand Down Expand Up @@ -62,20 +62,25 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
ref
);

const blockProps = useBlockProps();

const innerBlocksProps = useInnerBlocksProps(
{},
const hasBlockOverlay = useBlockOverlayActive( clientId );
const blockProps = useBlockProps(
{
value: blocks,
onInput,
onChange,
renderAppender: blocks?.length
? undefined
: InnerBlocks.ButtonBlockAppender,
}
className: hasBlockOverlay
? 'block-library-block__reusable-block-container block-editor-block-content-overlay'
: 'block-library-block__reusable-block-container',
},
{ isDisabled: hasBlockOverlay }
);

const innerBlocksProps = useInnerBlocksProps( blockProps, {
value: blocks,
onInput,
onChange,
renderAppender: blocks?.length
? undefined
: InnerBlocks.ButtonBlockAppender,
} );

if ( hasAlreadyRendered ) {
return (
<div { ...blockProps }>
Expand Down Expand Up @@ -108,36 +113,28 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {

return (
<RecursionProvider>
<div { ...blockProps }>
{ canRemove && (
<BlockControls>
<ToolbarGroup>
<ToolbarButton
onClick={ () =>
convertBlockToStatic( clientId )
}
label={ __( 'Convert to regular blocks' ) }
icon={ ungroup }
showTooltip
/>
</ToolbarGroup>
</BlockControls>
) }
<InspectorControls>
<PanelBody>
<TextControl
label={ __( 'Name' ) }
value={ title }
onChange={ setTitle }
{ canRemove && (
<BlockControls>
<ToolbarGroup>
<ToolbarButton
onClick={ () => convertBlockToStatic( clientId ) }
label={ __( 'Convert to regular blocks' ) }
icon={ ungroup }
showTooltip
/>
</PanelBody>
</InspectorControls>
<BlockContentOverlay
clientId={ clientId }
wrapperProps={ innerBlocksProps }
className="block-library-block__reusable-block-container"
/>
</div>
</ToolbarGroup>
</BlockControls>
) }
<InspectorControls>
<PanelBody>
<TextControl
label={ __( 'Name' ) }
value={ title }
onChange={ setTitle }
/>
</PanelBody>
</InspectorControls>
<div { ...innerBlocksProps } />
</RecursionProvider>
);
}
61 changes: 35 additions & 26 deletions packages/block-library/src/navigation/edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
ContrastChecker,
getColorClassName,
Warning,
__experimentalUseBlockOverlayActive as useBlockOverlayActive,
} from '@wordpress/block-editor';
import { EntityProvider } from '@wordpress/core-data';

Expand Down Expand Up @@ -320,33 +321,41 @@ function Navigation( {

const textDecoration = attributes.style?.typography?.textDecoration;

const blockProps = useBlockProps( {
ref: navRef,
className: classnames( className, {
'items-justified-right': justifyContent === 'right',
'items-justified-space-between': justifyContent === 'space-between',
'items-justified-left': justifyContent === 'left',
'items-justified-center': justifyContent === 'center',
'is-vertical': orientation === 'vertical',
'no-wrap': flexWrap === 'nowrap',
'is-responsive': 'never' !== overlayMenu,
'has-text-color': !! textColor.color || !! textColor?.class,
[ getColorClassName(
'color',
textColor?.slug
) ]: !! textColor?.slug,
'has-background': !! backgroundColor.color || backgroundColor.class,
[ getColorClassName(
'background-color',
backgroundColor?.slug
) ]: !! backgroundColor?.slug,
[ `has-text-decoration-${ textDecoration }` ]: textDecoration,
} ),
style: {
color: ! textColor?.slug && textColor?.color,
backgroundColor: ! backgroundColor?.slug && backgroundColor?.color,
const hasBlockOverlay = useBlockOverlayActive( clientId );
const blockProps = useBlockProps(
{
ref: navRef,
className: classnames( className, {
'items-justified-right': justifyContent === 'right',
'items-justified-space-between':
justifyContent === 'space-between',
'items-justified-left': justifyContent === 'left',
'items-justified-center': justifyContent === 'center',
'is-vertical': orientation === 'vertical',
'no-wrap': flexWrap === 'nowrap',
'is-responsive': 'never' !== overlayMenu,
'has-text-color': !! textColor.color || !! textColor?.class,
[ getColorClassName(
'color',
textColor?.slug
) ]: !! textColor?.slug,
'has-background':
!! backgroundColor.color || backgroundColor.class,
[ getColorClassName(
'background-color',
backgroundColor?.slug
) ]: !! backgroundColor?.slug,
[ `has-text-decoration-${ textDecoration }` ]: textDecoration,
'block-editor-block-content-overlay': hasBlockOverlay,
} ),
style: {
color: ! textColor?.slug && textColor?.color,
backgroundColor:
! backgroundColor?.slug && backgroundColor?.color,
},
},
} );
{ isDisabled: hasBlockOverlay }
);

const overlayClassnames = classnames( {
'has-text-color':
Expand Down