Editor: Add new block support for syncing sibling block styles#76489
Editor: Add new block support for syncing sibling block styles#76489mikachan wants to merge 25 commits into
Conversation
|
Size Change: +2.27 kB (+0.03%) Total Size: 7.74 MB
ℹ️ View Unchanged
|
|
Is it possible to sync all |
Not yet, but we could add support for something like |
Or maybe |
|
Flaky tests detected in d5fb0d4. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/23850757165
|
That makes sense, and I don't think we need the groups at all for now. I've removed them in 844bb86. We can add them back later if we think they're needed. I've made some further changes based on discussions with @aaronrobertshaw:
Side note: We've also been looking into how we can achieve the same functionality through block bindings. It would be great if we could use existing functionality to achieve this, but I'll keep working on this PR until it's clearer which option is best. |

What?
Closes #76330
This PR adds a new
__experimentalSyncedStylesblock support API that lets inner blocks of the same type automatically share style changes within a parent scope (e.g. all Accordion Heading blocks within an Accordion).Why?
When editing a repeating pattern like an accordion, users may expect a consistent appearance across all headings or content panels. Without this, they have to manually reapply the same colour, typography, or border changes to every sibling block individually. This PR introduces a "sibling style sync" system so style changes are propagated automatically, with per-block opt-out and parent-level controls to disable sync entirely.
How?
Mostly through a new block support:
__experimentalSyncedStylesInner blocks declare support with:
withSyncedStylesHOC (in hooks/hooks/synced-styles.js):setAttributesfor blocks with the support and routes style-group attributes through__experimentalUpdateSyncedBlockAttributes, which propagates the change to all linked siblings in the scope viaregistry.batch()(single undo step).__unstableMarkNextChangeAsNotPersistent, so newly inserted blocks immediately match their siblings without creating a separate undo entry.styleSyncUnlinkedattribute on page reload.Store additions (in store/private-actions.js, store/private-selectors.js, store/reducer.js):
__experimentalUpdateSyncedBlockAttributes,__experimentalUnlinkBlockStyleSync,__experimentalRelinkBlockStyleSync__experimentalGetSyncedStylesBlocks,__experimentalGetSyncedStylesScopeClientId,__experimentalIsBlockStyleSyncUnlinkedsyncedStyles(keyed by${blockName}:${clientId}) cleaned up on block removalInspector UI:
SyncedStylesControl(inner block inspector): shows "Styles synced with N other X blocks" notice with an Unlink this block button; switches to a warning when unlinked, with a Re-sync styles button.SyncedStylesParentControl(scope block inspector): "Style syncing" panel with a toggle per child type to globally disable sync for that type.synced-styles-utils.js:
partitionAttributesByGroups: splits changed attributes into synced vs unsynced bucketsmergeStyleByGroups: merges incoming synced style sub-keys into a sibling's style without clobbering its unsynced sub-keysfindDescendantsOfType: recursive block tree search used to find all sibling candidates in a scopeApplied to the Accordion block:
syncDescendantStylesattribute and the parent controlThird-party block support:
This API is not specific to the Accordion block. Any block can opt in via block.json, including third-party parent blocks:
No PHP or JS registration is required beyond block.json. The sync behaviour, inspector controls, and unlink/re-sync UI are all applied automatically by the block editor for any block type that declares this support.
Testing Instructions
Screenshots or screencast
New settings under Settings in the block inspector:

Notice shown on synced inner blocks:

Use of AI Tools
This PR was developed with assistance from Claude Code and Cursor.