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

Add a dot before the parent block selector when there are unsaved changes in the Reusable block #1

Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { getBlockType, store as blocksStore } from '@wordpress/blocks';
import { ToolbarButton } from '@wordpress/components';
import { ToolbarButton, Slot } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { __, sprintf } from '@wordpress/i18n';
import { useRef } from '@wordpress/element';
Expand Down Expand Up @@ -78,6 +78,7 @@ export default function BlockParentSelector() {
ref={ nodeRef }
{ ...showMoversGestures }
>
<Slot name="parent-block-selector-unsaved-changes-indicator" />
<ToolbarButton
className="block-editor-block-parent-selector__button"
onClick={ () => selectBlock( firstParentClientId ) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,31 @@
border-radius: $radius-block-ui;
}
}

// styles for parent block selector when parent block has changes
.block-editor-block-parent-selector.parent-block-has-changes {
left: calc(-#{$grid-unit-60} - #{$grid-unit-30} - #{$border-width});

// increase the width of parent selector to make room for the dot
.block-editor-block-parent-selector__button {
width: $grid-unit-60 + $grid-unit-20;
}

// move the parent selector icon to right side to make room for the dot
.block-editor-block-icon {
margin-right: -15px;
}

// add the dot before the parent selector icon
.parent-block-selector-unsaved-changes-indicator {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: var(--wp-admin-theme-color);
border-radius: 4px;
height: 8px;
width: 8px;
margin: 0 12px;
}
}

4 changes: 4 additions & 0 deletions packages/block-editor/src/components/block-switcher/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ToolbarButton,
ToolbarGroup,
ToolbarItem,
Slot,
} from '@wordpress/components';
import {
switchToBlockType,
Expand Down Expand Up @@ -147,6 +148,9 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => {
} }
icon={
<>
{ isReusable && (
Copy link

Choose a reason for hiding this comment

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

I think a slot renders nothing if there are no fills, so it should be fine to just render the slot without the surrounding isReusable logic.

<Slot name="block-unsaved-changes-indicator" />
) }
<BlockIcon
icon={ icon }
className="block-editor-block-switcher__toggle"
Expand Down
10 changes: 10 additions & 0 deletions packages/block-editor/src/components/block-switcher/style.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
.block-editor-block-switcher {
position: relative;

// Show dot before the block switcher in block toolbar if block has edits
.block-unsaved-changes-indicator {
position: relative;
background: var(--wp-admin-theme-color);
border-radius: 4px;
height: 8px;
width: 8px;
margin-right: 8px;
}
}

// Show an indicator triangle.
Expand Down
9 changes: 9 additions & 0 deletions packages/block-editor/src/components/block-toolbar/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
}
}

// move contextual toolbar to right when parent block has changes
.block-editor-block-contextual-toolbar.parent-block-has-changes:not(.is-fixed) {
margin-left: calc(#{$grid-unit-60} + #{$grid-unit-30});

.show-icon-labels & {
margin-left: 0;
}
}

.block-editor-block-parent-selector {
position: absolute;
top: -$border-width;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* WordPress dependencies
*/
import { Fill } from '@wordpress/components';
import { useEffect } from '@wordpress/element';

function UnsavedChangesIndicator() {
useEffect( () => {
// add class to the parent selector to increase it's width
const parentSelectorBtn = document.querySelector(
'.block-editor-block-parent-selector'
);
parentSelectorBtn.classList.add( 'parent-block-has-changes' );
// add class to the contextual toolbar to move it to the right side
const contextualToolBar = document.querySelector(
'.block-editor-block-contextual-toolbar'
);
contextualToolBar.classList.add( 'parent-block-has-changes' );

return () => {
// remove classes from the parent selector and contextual toolbar when component unmounts
document
.querySelector( '.block-editor-block-parent-selector' )
.classList.remove( 'parent-block-has-changes' );
document
.querySelector( '.block-editor-block-contextual-toolbar' )
.classList.remove( 'parent-block-has-changes' );
};
}, [] );
Copy link

Choose a reason for hiding this comment

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

I'm not in favour of the modification of other parent elements when this renders. Is there a way to achieve the same result without that being required?

Copy link
Owner Author

Choose a reason for hiding this comment

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

The unsaved changes indicator increases the width of the parent selector button. Since the parent selector button is positioned absolutely to the contextual toolbar, it leads to a state like this:

image

That's why a new class block-has-changes is added to the contextual toolbar to handle the alignment issues.

I am not sure how to achieve this without affecting the contextual toolbar. If you have any suggestions, I will be more than happy to try them out 🙂

Copy link

Choose a reason for hiding this comment

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

Since the parent selector button is positioned absolutely to the contextual toolbar, it leads to a state like this

Interesting that this is positioned absolutely. That sounds like the core of the problem. Is there a way to style it so that it's an inline element?


return (
<div className="parent-block-selector-unsaved-changes-indicator"></div>
);
}

function ParentBlockSelectorUnsavedChangesIndicator() {
return (
<>
<Fill name="parent-block-selector-unsaved-changes-indicator">
<UnsavedChangesIndicator />
</Fill>
</>
);
}

export default ParentBlockSelectorUnsavedChangesIndicator;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* WordPress dependencies
*/
import { Fill } from '@wordpress/components';

function UnsavedChangesIndicator() {
return <div className="block-unsaved-changes-indicator"></div>;
}

function SelectedBlockUnsavedChangesIndicator() {
return (
<>
<Fill name="block-unsaved-changes-indicator">
<UnsavedChangesIndicator />
</Fill>
</>
);
}

export default SelectedBlockUnsavedChangesIndicator;
2 changes: 2 additions & 0 deletions packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ export { default as BlockSettingsMenuControls } from './block-settings-menu-cont
export { default as BlockTitle } from './block-title';
export { default as BlockToolbar } from './block-toolbar';
export { default as BlockTools } from './block-tools';
export { default as __experimentalParentBlockSelectorUnsavedChangesIndicator } from './block-unsaved-changes-indicator/parent-block-selector-unsaved-changes-indicator';
export { default as __experimentalSelectedBlockUnsavedChangesIndicator } from './block-unsaved-changes-indicator/selected-block-unsaved-changes-indicator';
export {
default as CopyHandler,
useClipboardHandler as __unstableUseClipboardHandler,
Expand Down
28 changes: 28 additions & 0 deletions packages/block-library/src/block/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ import {
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
__experimentalUseNoRecursiveRenders as useNoRecursiveRenders,
__experimentalBlockContentOverlay as BlockContentOverlay,
__experimentalParentBlockSelectorUnsavedChangesIndicator as ParentBlockSelectorUnsavedChangesIndicator,
__experimentalSelectedBlockUnsavedChangesIndicator as SelectedBlockUnsavedChangesIndicator,
InnerBlocks,
BlockControls,
InspectorControls,
useBlockProps,
Warning,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { store as reusableBlocksStore } from '@wordpress/reusable-blocks';
import { ungroup } from '@wordpress/icons';
Expand Down Expand Up @@ -68,6 +71,23 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
[ ref, clientId ]
);

const { isChildSelected, isSelected } = useSelect( ( select ) => {
const { getBlockParents, getSelectedBlockClientId } = select(
blockEditorStore
);
const selectedBlockClientId = getSelectedBlockClientId();
const _isSelected = selectedBlockClientId === clientId;

const parents = getBlockParents( selectedBlockClientId );
const firstParentClientId = parents[ parents.length - 1 ];
const _isChildSelected = firstParentClientId === clientId;

return {
isChildSelected: _isChildSelected,
isSelected: _isSelected,
};
}, [] );

const {
__experimentalConvertBlockToStatic: convertBlockToStatic,
} = useDispatch( reusableBlocksStore );
Expand Down Expand Up @@ -156,6 +176,14 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
return (
<RecursionProvider>
<div { ...blockProps }>
{ isSelected && hasEdits && (
<SelectedBlockUnsavedChangesIndicator />
) }

{ isChildSelected && hasEdits && (
<ParentBlockSelectorUnsavedChangesIndicator />
) }

<BlockControls>
<ToolbarGroup>
<ToolbarButton
Expand Down