Skip to content

Editor: Extend Apply globally to sibling blocks within a parent - #83339

Open
mikachan wants to merge 6 commits into
trunkfrom
try/apply-styles-to-siblings
Open

mikachan wants to merge 6 commits into
trunkfrom
try/apply-styles-to-siblings

Conversation

@mikachan

@mikachan mikachan commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

What?

Part of #76330
Alternative to #77097

Adds a second scope to the Styles control in the block Advanced panel, so a block's styles can be applied to the other blocks of its type inside the parent they share, as well as to every block of that type across the site.

Why?

There's currently no way to share the styles of an inner block with its siblings. If an Accordion has five headings, or a Tabs block has four panels, each one has to be styled by hand, and adding a new item means re-applying everything. See #76330 for more details.

This PR takes the approach from #77097, but builds it on the current version of the control rather than the one #77097 was written against. Since that PR was opened, #79839 gave "Apply globally" a review modal where each style is a row you can tick, and #80990 renamed the file. Reusing the review modal also fixes the main weakness of the earlier prototype, which copied every style attribute at once and overwrote whatever the siblings already had.

How?

A new useSiblingScope hook walks up from the selected block to the nearest ancestor that holds more than one block of the same type, and returns that ancestor's title along with the blocks to apply to. For an Accordion Heading that ancestor is the Accordion; for a Tab Panel it's Tab Panels; for a Button it's Buttons. Blocks of the same type anywhere inside the ancestor count, not just immediate children, because the blocks that should match are usually a level or two down.

When both scopes are available the control shows a radio group, and Global Styles stays selected by default, so nothing changes for existing users unless the sibling scope is chosen. Both scopes then open the same review modal, and only the ticked rows are applied. On the sibling scope the "Current" column means the value the siblings already share, or "Varies" when they disagree, since there's no single current value to show across several blocks.

Testing Instructions

  1. Insert a Buttons block and add three buttons with some text in each.
  2. Select the first button, then open Settings → Advanced in the sidebar. You should see a "Styles" section with an "Apply styles to" radio group and a "Review and apply" button.
  3. Check that "All Button blocks on the site" is selected by default.
  4. Switch to the Styles tab and give the first button a text colour and a font size.
  5. Back in Advanced, choose "All Button blocks in this Buttons" and press "Review and apply".
  6. Check the modal is titled "Apply Button styles in this Buttons", lists the two styles you changed with "Current" and "New" columns, and starts with every row ticked.
  7. Untick one of the rows and press Apply. Only the ticked style should be copied to the other two buttons, and a snackbar should read "Button styles applied in this Buttons."
  8. Check the unticked style is unchanged on the other buttons, and that any styles they already had of their own are untouched.
  9. Undo those changes. All the siblings should revert together in a single undo step.
  10. Give the second and third buttons two different background colours. Select the first button, set a background colour on it, choose the sibling scope, and press "Review and apply". The "Current" column for Background colour should read "Varies".
  11. Set a colour from the theme palette on the first button rather than a custom one, then apply it to the siblings. The other buttons should pick up the palette colour as a preset, not a hardcoded hex value.
  12. Select a block with no same-type siblings, such as a standalone Heading. Advanced should show only the "Apply globally" button with no radio group, and pushing to Global Styles should behave exactly as it does on trunk.
  13. Try the same steps with an Accordion. Select an Accordion Heading inside one of the items, and check the sibling option reads "in this Accordion" and applies to the headings in the other items.
  14. Activate a classic theme, such as Twenty Twenty-One. The "Styles" control should now appear for a button inside Buttons, with the sibling scope only and no radio group, and should not appear for a standalone Heading.

Screenshots or screencast

Before After
image image

Use of AI Tools

Claude Code

@mikachan mikachan added [Type] Enhancement A suggestion for improvement. [Feature] Nested / Inner Blocks Anything related to the experience of nested/inner blocks inside a larger container, like Group or P [Package] Editor /packages/editor labels Sep 22, 2026
@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

📦 Bundle size

Size Change: +1.44 kB (+0.02%)

Total Size: 8.23 MB

📦 View Changed
Filename Size Change
build/scripts/editor/index.min.js 615 kB +1.44 kB (+0.24%)

9985b55 Run

⚡ Performance

Show the results

Client side metrics exclude the server response time.

front-end-block-theme

Metric 96e86d6 trunk % Change
timeToFirstByte 60.55 ms +10.24% -4.21% 56.35 ms +8.43% -0.98% 7.45%
largestContentfulPaint 98 ms +10.2% -4.08% 100 ms +2% -4% -2%
lcpMinusTtfb 36.4 ms +16.9% -2.34% 40.4 ms +8.54% -14.85% -9.9%
wpBeforeTemplate 30.14 ms +13.87% -2.52% 28.32 ms +7.8% -2.12% 6.43%
wpTemplate 25.16 ms +5.48% -4.61% 24.59 ms +1.95% -3.13% 2.32%
wpTotal 56.72 ms +9.08% -4.64% 52.38 ms +9.03% -0.53% 8.29%
wpMemoryUsage 7.61 MB +0% -0% 7.56 MB +0% -0% 0.67%
wpDbQueries 17 +0% -0% 17 +0% -0% 0%

front-end-classic-theme

Metric 96e86d6 trunk % Change
timeToFirstByte 52.5 ms +7.62% -3.24% 47.4 ms +3.48% -1.16% 10.76%
largestContentfulPaint 112 ms +3.57% -3.57% 102 ms +1.96% -1.96% 9.8%
lcpMinusTtfb 59.05 ms +1.44% -3.13% 54.35 ms +3.86% -2.39% 8.65%
wpBeforeTemplate 28.62 ms +7.83% -3.07% 26.08 ms +7.4% -2.53% 9.74%
wpTemplate 19.74 ms +3.5% -2.43% 17.99 ms +1.78% -1.89% 9.73%
wpTotal 49.16 ms +5.57% -3.84% 44.21 ms +3.73% -1.02% 11.2%
wpMemoryUsage 6.22 MB +0% -0% 6.18 MB +0% -0% 0.77%
wpDbQueries 14 +0% -0% 14 +0% -0% 0%

media-processing

Metric 96e86d6 trunk % Change
mediaProcessingJpeg 405.94 ms +0.86% -0.62% 399.78 ms +2.04% -0.63% 1.54%
mediaProcessingAvif 6115.85 ms +0.18% -0.11% 6084.29 ms +0.06% -0.28% 0.52%
mediaProcessingJpegToAvif 4218.39 ms +0.04% -0.19% 4197.1 ms +0.18% -0.49% 0.51%

media-upload

Metric 96e86d6 trunk % Change
jpegUploadProcessing 1468.64 ms +36.49% -1.21% 1421.26 ms +1.01% -0.15% 3.33%
pngUploadProcessing 200.82 ms +3.19% -2.8% 214.3 ms +5.02% -4.64% -6.29%
largeJpegUploadProcessing 1427.02 ms +0.86% -0.38% 1423.66 ms +0.79% -0.99% 0.24%
multipleImageUploadProcessing 2126.78 ms +2.07% -9.72% 1560.67 ms +1.65% -0.69% 36.27%

post-editor

Metric 96e86d6 trunk % Change
serverResponse 514.37 ms +2.87% -9.85% 524.57 ms +0.88% -9.77% -1.94%
firstPaint 229.77 ms +13.26% -31.78% 236.07 ms +6.64% -13.1% -2.67%
domContentLoaded 1111.41 ms +1.3% -2.01% 1087.64 ms +1.05% -1.53% 2.19%
loaded 1112.9 ms +1.3% -2.04% 1089.01 ms +1.06% -1.53% 2.19%
firstContentfulPaint 459.25 ms +1.67% -3.92% 446.61 ms +1.14% -2.7% 2.83%
firstBlock 3300.35 ms +1.01% -0.14% 3278.55 ms +0.7% -0.85% 0.66%
type 18.88 ms +1.69% -2.97% 19.29 ms +4.35% -5.91% -2.13%
typeWithoutInspector 17.4 ms +8.79% -5.98% 19.5 ms +5.69% -5.23% -10.77%
typeWithTopToolbar 23.78 ms +11.31% -5.76% 25.33 ms +2.76% -5.37% -6.12%
typeContainer 9.11 ms +4.17% -12.07% 8.72 ms +8.94% -6.88% 4.47%
focus 71.04 ms +10.28% -8.92% 71.21 ms +13.79% -1.8% -0.24%
firstFocus 202.88 ms +0% -0% 207.93 ms +0% -0% -2.43%
selectAll 546.37 ms +1.97% -0.41% 538.35 ms +0.5% -1.11% 1.49%
listViewOpen 61.84 ms +3.74% -9.56% 77.39 ms +5.54% -3.39% -20.09%
inserterOpen 22.99 ms +12.7% -15.18% 23.43 ms +3.71% -2.05% -1.88%
inserterHover 2.19 ms +12.33% -11.87% 3.05 ms +8.2% -11.8% -28.2%
inserterSearch 7.83 ms +11.88% -4.98% 7.71 ms +9.21% -8.17% 1.56%
loadPatterns 654.82 ms +4.36% -5.8% 641.82 ms +0.93% -2.4% 2.03%
wpTotal 504.66 ms +2.92% -10.01% 514.24 ms +0.97% -9.95% -1.86%
wpMemoryUsage 13.14 MB +0% -0% 13.09 MB +0% -0% 0.37%
wpDbQueries 54 +0% -0% 54 +0% -0% 0%

site-editor

Metric 96e86d6 trunk % Change
serverResponse 505.74 ms +3.32% -2.42% 507.34 ms +3.6% -5.3% -0.32%
firstPaint 248.63 ms +11.74% -10.35% 235.89 ms +9.75% -7.98% 5.4%
domContentLoaded 1129.24 ms +1.13% -0.65% 1116.08 ms +0.74% -1.06% 1.18%
loaded 1130.48 ms +1.12% -0.65% 1117.15 ms +0.75% -1.05% 1.19%
firstContentfulPaint 457.69 ms +1.41% -2.88% 448.71 ms +1.98% -2.13% 2%
firstBlock 4141.14 ms +1.31% -1.29% 4089.51 ms +1.1% -0.5% 1.26%
type 18.56 ms +5.77% -4.69% 20.03 ms +5.99% -7.04% -7.34%
navigate 100.37 ms +13.52% -3.48% 115.2 ms +6.69% -6.51% -12.87%
loadPatterns 1306.8 ms +3.88% -6.05% 1277.35 ms +8.08% -5.43% 2.31%
loadPages 1045.78 ms +2.57% -1.89% 1068.34 ms +0.95% -1.35% -2.11%
wpTotal 495.91 ms +3.35% -2.35% 496.5 ms +3.99% -5.16% -0.12%
wpMemoryUsage 12.11 MB +0% -0% 12.06 MB +0% -0% 0.4%
wpDbQueries 43 +2.33% -0% 43.5 +1.15% -1.15% -1.15%

9985b55 Run

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Preset handling can drop styles or preserve conflicting attributes, while grouped-row current values can be inaccurate.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
What changed in this PR

Adds parent-scoped style application for matching sibling blocks while retaining site-wide Global Styles support.

Changes:

  • Detects matching blocks within the nearest shared ancestor.
  • Extends the review modal for sibling values and selective application.
  • Adds shared style utilities and unit tests.
File Description
use-review-rows.js Formats sibling review values.
sibling-styles.jsdom.test.js Tests sibling style operations.
style-paths.js Extracts shared style-path helpers.
sibling-styles.js Builds sibling attribute updates.
index.jsx Adds scope selection and application flow.
apply-globally-modal.jsx Supports sibling-scoped review.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/editor/src/hooks/push-changes-to-global-styles/sibling-styles.js Outdated
mikachan and others added 2 commits September 24, 2026 11:06
Not every `var:preset|…` value is backed by a block attribute. A spacing
size, a link colour and a per-side border colour are all stored in `style`
on the source block, but `getSiblingStylesUpdate` treated any preset value
as attribute-carried: it cleared the sibling's value at that path and never
wrote the new one, so applying such a row silently did nothing.

Only clear the path when the row actually has a preset attribute to carry
the value, and copy everything else into `style` as-is.

Also clear a preset attribute the sibling already has when a custom value is
copied over the same path, so the leftover preset class can't keep winning.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`getSiblingCurrentValue` read a single `primaryPath`, which doesn't describe
a grouped row. For the flat border row that path is `border`, so the whole
object came back including the radius and the per-side sub-objects that have
rows of their own: siblings differing only in radius reported "Varies", and
because `border` has no entry in `STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE`, a
sibling's `borderColor` preset was invisible. A link colour row also writes
the hover colour but never compared it, hiding a difference it overwrites.

Compare across every path the row writes, and assemble a border row's
displayed value from the properties it actually covers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The modal can report inaccurate current values for inherited, hover-only, and per-side border styles.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (2)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Use hover path when base link color is unset

packages/​editor/​src/​hooks/​push-changes-to-global-styles/​sibling-styles.js:82

When a link-color row contains only the hover path, primaryPath still points to the unset base color, so siblings sharing a hover color show “—” even though Apply will overwrite that value. Derive the displayed value from the covered hover path when the primary path is unset.

Medium severity Resolve inherited global styles when displaying current values

packages/​editor/​src/​hooks/​push-changes-to-global-styles/​sibling-styles.js:135

The “Current” value is derived only from local sibling attributes, so siblings that all inherit the same Global Styles value show “—” (and an explicit equivalent on one sibling becomes “Varies”) instead of the value they currently share. Resolve unset paths against the merged block style before displaying and comparing them.

Comment thread packages/editor/src/hooks/push-changes-to-global-styles/sibling-styles.js Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The sibling review can display incorrect current values for inherited and hover-only styles.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Resolve inherited styles before displaying current values

packages/​editor/​src/​hooks/​push-changes-to-global-styles/​sibling-styles.js:178

When a sibling inherits this style from Global Styles, these reads return undefined, so “Current” shows “—” (or “Varies” against an equivalent explicit override) even though applying will replace a real rendered value. Resolve missing local paths against the merged block-type styles before comparing and formatting them.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The sibling-scope behavior is coherently integrated and covered by focused tests, with previously identified grouped-style and preset issues resolved.

Review effort: Balanced
Findings: None

@mikachan
mikachan marked this pull request as ready for review September 24, 2026 16:28
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: mikachan <mikachan@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Nested / Inner Blocks Anything related to the experience of nested/inner blocks inside a larger container, like Group or P [Package] Editor /packages/editor [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants