diff --git a/packages/block-editor/src/components/block-card/index.js b/packages/block-editor/src/components/block-card/index.js
index dab832861ae661..405a741125635f 100644
--- a/packages/block-editor/src/components/block-card/index.js
+++ b/packages/block-editor/src/components/block-card/index.js
@@ -30,9 +30,12 @@ function BlockCard( { title, icon, description, blockType, className } ) {
const isOffCanvasNavigationEditorEnabled =
window?.__experimentalEnableOffCanvasNavigationEditor === true;
- const { parentNavBlockClientId } = useSelect( ( select ) => {
- const { getSelectedBlockClientId, getBlockParentsByBlockName } =
- select( blockEditorStore );
+ const { parentNavBlockClientId, isSynced } = useSelect( ( select ) => {
+ const {
+ getSelectedBlockClientId,
+ getBlockParentsByBlockName,
+ areInnerBlocksControlled,
+ } = select( blockEditorStore );
const _selectedBlockClientId = getSelectedBlockClientId();
@@ -42,6 +45,7 @@ function BlockCard( { title, icon, description, blockType, className } ) {
'core/navigation',
true
)[ 0 ],
+ isSynced: areInnerBlocksControlled( _selectedBlockClientId ),
};
}, [] );
@@ -65,6 +69,11 @@ function BlockCard( { title, icon, description, blockType, className } ) {
{ title }
+ { isSynced && (
+
+ Synced
+
+ ) }
{ description }
diff --git a/packages/block-editor/src/components/block-card/style.scss b/packages/block-editor/src/components/block-card/style.scss
index 1b2156c19fa797..e0bad067299882 100644
--- a/packages/block-editor/src/components/block-card/style.scss
+++ b/packages/block-editor/src/components/block-card/style.scss
@@ -17,6 +17,18 @@
}
}
+.block-editor-block-card__sync-status {
+ margin-block-start: $grid-unit-05;
+ margin-block-end: $grid-unit-15;
+ display: block;
+ width: min-content;
+ color: #fff;
+ background-color: var(--wp-block-synced-color);
+ padding: 3px 6px;
+ font-size: 0.9em;
+ border-radius: $radius-block-ui;
+}
+
.block-editor-block-card__description {
font-size: $default-font-size;
}
diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js
index 70456ac213fc3b..93920260c01e6b 100644
--- a/packages/block-editor/src/components/block-list/block.js
+++ b/packages/block-editor/src/components/block-list/block.js
@@ -103,6 +103,7 @@ function BlockListBlock( {
isContentBlock,
isContentLocking,
isTemporarilyEditingAsBlocks,
+ isSyncedBlock,
} = useSelect(
( select ) => {
const {
@@ -110,9 +111,13 @@ function BlockListBlock( {
__unstableGetContentLockingParent,
getTemplateLock,
__unstableGetTemporarilyEditingAsBlocks,
+ areInnerBlocksControlled,
} = select( blockEditorStore );
const _hasContentLockedParent =
!! __unstableGetContentLockingParent( clientId );
+
+ const _isSyncedBlock = areInnerBlocksControlled( clientId );
+
return {
themeSupportsLayout: getSettings().supportsLayout,
isContentBlock:
@@ -125,6 +130,7 @@ function BlockListBlock( {
! _hasContentLockedParent,
isTemporarilyEditingAsBlocks:
__unstableGetTemporarilyEditingAsBlocks() === clientId,
+ isSyncedBlock: _isSyncedBlock,
};
},
[ name, clientId ]
@@ -153,6 +159,7 @@ function BlockListBlock( {
toggleSelection={ toggleSelection }
__unstableLayoutClassNames={ layoutClassNames }
__unstableParentLayout={ parentLayout }
+ __unstableIsSyncedBlock={ isSyncedBlock }
/>
);
@@ -236,6 +243,7 @@ function BlockListBlock( {
'is-content-locked-temporarily-editing-as-blocks':
isTemporarilyEditingAsBlocks,
'is-content-block': hasContentLockedParent && isContentBlock,
+ 'is-synced': isSyncedBlock,
},
dataAlign && themeSupportsLayout && `align${ dataAlign }`,
className
diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss
index 7219275196d8fb..9fde919e62ac65 100644
--- a/packages/block-editor/src/components/block-list/content.scss
+++ b/packages/block-editor/src/components/block-list/content.scss
@@ -435,3 +435,23 @@
transition: all 0.3s;
transform-origin: top center;
}
+
+// This needs moving to a generic file as it now applies to all blocks that are "synced".
+.is-outline-mode .block-editor-block-list__block:not(.remove-outline).wp-block.is-synced {
+
+ &.is-highlighted,
+ &.is-selected {
+ box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-block-synced-color);
+ }
+
+ &.block-editor-block-list__block:not([contenteditable]):focus {
+ &::after {
+ box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-block-synced-color);
+
+ // Show a light color for dark themes.
+ .is-dark-theme & {
+ box-shadow: 0 0 0 var(--wp-admin-border-width-focus) $dark-theme-focus;
+ }
+ }
+ }
+}
diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js
index 6727851e1647bf..7868eb51df58aa 100644
--- a/packages/block-editor/src/components/block-toolbar/index.js
+++ b/packages/block-editor/src/components/block-toolbar/index.js
@@ -9,12 +9,7 @@ import classnames from 'classnames';
import { useSelect, useDispatch } from '@wordpress/data';
import { useRef } from '@wordpress/element';
import { useViewportMatch } from '@wordpress/compose';
-import {
- getBlockType,
- hasBlockSupport,
- isReusableBlock,
- isTemplatePart,
-} from '@wordpress/blocks';
+import { getBlockType, hasBlockSupport } from '@wordpress/blocks';
import { ToolbarGroup } from '@wordpress/components';
/**
@@ -43,6 +38,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
isValid,
isVisual,
isContentLocked,
+ isSynced,
} = useSelect( ( select ) => {
const {
getBlockName,
@@ -52,6 +48,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
getBlockRootClientId,
getSettings,
__unstableGetContentLockingParent,
+ areInnerBlocksControlled,
} = select( blockEditorStore );
const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
@@ -76,6 +73,7 @@ const BlockToolbar = ( { hideDragHandle } ) => {
isContentLocked: !! __unstableGetContentLockingParent(
selectedBlockClientId
),
+ isSynced: areInnerBlocksControlled( selectedBlockClientId ),
};
}, [] );
@@ -114,8 +112,6 @@ const BlockToolbar = ( { hideDragHandle } ) => {
const shouldShowVisualToolbar = isValid && isVisual;
const isMultiToolbar = blockClientIds.length > 1;
- const isSynced =
- isReusableBlock( blockType ) || isTemplatePart( blockType );
const classes = classnames( 'block-editor-block-toolbar', {
'is-showing-movers': shouldShowMovers,
diff --git a/packages/block-editor/src/components/use-block-display-information/index.js b/packages/block-editor/src/components/use-block-display-information/index.js
index e9b1e8865a05cf..2a6d2089e82872 100644
--- a/packages/block-editor/src/components/use-block-display-information/index.js
+++ b/packages/block-editor/src/components/use-block-display-information/index.js
@@ -2,11 +2,7 @@
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
-import {
- store as blocksStore,
- isReusableBlock,
- isTemplatePart,
-} from '@wordpress/blocks';
+import { store as blocksStore } from '@wordpress/blocks';
/**
* Internal dependencies
@@ -20,7 +16,7 @@ import { store as blockEditorStore } from '../../store';
*
* @typedef {Object} WPBlockDisplayInformation
*
- * @property {boolean} isSynced True if is a reusable block or template part
+ * @property {boolean} isSynced True if inner blocks are controlled.
* @property {string} title Human-readable block type label.
* @property {WPIcon} icon Block type icon.
* @property {string} description A detailed block type description.
@@ -46,8 +42,11 @@ export default function useBlockDisplayInformation( clientId ) {
return useSelect(
( select ) => {
if ( ! clientId ) return null;
- const { getBlockName, getBlockAttributes } =
- select( blockEditorStore );
+ const {
+ getBlockName,
+ getBlockAttributes,
+ areInnerBlocksControlled,
+ } = select( blockEditorStore );
const { getBlockType, getActiveBlockVariation } =
select( blocksStore );
const blockName = getBlockName( clientId );
@@ -55,8 +54,7 @@ export default function useBlockDisplayInformation( clientId ) {
if ( ! blockType ) return null;
const attributes = getBlockAttributes( clientId );
const match = getActiveBlockVariation( blockName, attributes );
- const isSynced =
- isReusableBlock( blockType ) || isTemplatePart( blockType );
+ const isSynced = areInnerBlocksControlled( clientId );
const blockTypeInfo = {
isSynced,
title: blockType.title,
diff --git a/packages/block-library/src/template-part/editor.scss b/packages/block-library/src/template-part/editor.scss
index a847ecec01f94d..4aaa788be3e942 100644
--- a/packages/block-library/src/template-part/editor.scss
+++ b/packages/block-library/src/template-part/editor.scss
@@ -24,21 +24,3 @@
padding: $grid-unit-20 0;
z-index: z-index(".block-library-template-part__selection-search");
}
-
-.is-outline-mode .block-editor-block-list__block:not(.remove-outline).wp-block-template-part,
-.is-outline-mode .block-editor-block-list__block:not(.remove-outline).is-reusable {
- &.is-highlighted,
- &.is-selected {
- box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-block-synced-color);
- }
-
- &.block-editor-block-list__block:not([contenteditable]):focus {
- &::after {
- box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-block-synced-color);
- // Show a light color for dark themes.
- .is-dark-theme & {
- box-shadow: 0 0 0 var(--wp-admin-border-width-focus) $dark-theme-focus;
- }
- }
- }
-}