Global Styles: Resolve per-level heading element styles in block inspector controls - #80495
Conversation
…controls Completes the heading-family portion of the element inheritance layer tracked in #80438 (follow-up to #77894). The block inspector now reflects styles set on a specific heading level (`styles.elements.h1`-`h6`) in addition to the shared `heading` element. Previously the resolver folded in only `styles.elements.heading` for `core/heading`, so anything written by the per-level tabs in Styles > Typography > Headings was invisible to inspector controls. Because `fontSize` is deliberately disabled at the "All headings" level, every Global Styles heading font size lands in `elements.hN` and never reached a control at all. - Engine: replace the hardcoded `BLOCK_TO_ROOT_ELEMENT` map with an optional, caller-supplied `elements` list on the resolve context, ordered low to high precedence so `h2` wins over `heading`. This keeps the engine agnostic of block-to-element mappings and removes core block names from the package. The element list joins the memo cache key so two heading levels no longer share an entry. - block-editor: map block name + `level` to element keys for the heading family (`core/heading`, `site-title`, `post-title`, `query-title`, `comments-title`, `term-name`, `site-tagline`). A level of 0 (a block rendered as `<p>`) folds no heading layer. `clientId` is read from the block edit context, so `useResolvedStyle`'s signature is unchanged and no new store subscription is added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Size Change: +326 B (0%) Total Size: 7.75 MB 📦 View Changed
|
|
Flaky tests detected in f1a60ff. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/29889956803
|
|
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 If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
ramonjd
left a comment
There was a problem hiding this comment.
I gave this a smoke test and it's working really well for top level elements. Also checked:
- buttons
- custom preset colors
- hover states inside elements
- the list of blocks in pr desc
It gets a bit weird when applying styles to elements inside blocks, e.g., Group > Elements > h2. Controls will show the top level value rather than the block's.
Not a huge deal I guess. Could be a follow up.
Thanks for getting this started! 🚀
| case 'core/query-title': | ||
| case 'core/comments-title': | ||
| case 'core/term-name': | ||
| case 'core/site-tagline': |
There was a problem hiding this comment.
I think core/accordion-heading is an h3. Should we add it?
There was a problem hiding this comment.
I think the accordion one might need a little more work, but I'll double-check tomorrow. Thanks for taking this for a spin!
There was a problem hiding this comment.
I got it working for the accordion heading: it needed different handling as it derives its heading level via context rather than it being set on the individual accordion heading (so that all accordion headings in the set of accordion items receive the same heading level). It's a bit hard-coded and possibly smelly, but I tried to keep it neat where I could. Let me know if you think it's too much, and we can roll back and look at it in a follow-up if need be.
I'm a little on the fence about all this hard-coding, but at least it's fairly internal for now, and we could always look at improving it in the future... in any case, here's how it's looking now, inheriting the heading element style:
There was a problem hiding this comment.
I'm a little on the fence about all this hard-coding, but at least it's fairly internal for now
Nice! I think it's okay. Is there an alternative in code?
My 2c is that this small fix makes headings consistent, and therefore better for the user. That to me is more important.
There was a problem hiding this comment.
Nice! I think it's okay. Is there an alternative in code?
My 2c is that this small fix makes headings consistent, and therefore better for the user. That to me is more important.
Same here. I think I was just musing out loud about the idea that at some point we might codify this in block.json in some way and make it a bit more API-ey than hard-coded.
But agreed — for now I think focusing on improving the UX while keeping the code fairly self-contained is likely the right path forward.
I haven't looked at an alternative in code, mostly I wanted to confidence check that we're okay with the hard-coding. It seems we both are for now 😄
| // block's own styles. `elements` is ordered low to high precedence, so a | ||
| // level-specific `h2` correctly wins over the generic `heading`. | ||
| const elementLayers = ( elements ?? [] ) | ||
| .map( ( elementName ) => styles.elements?.[ elementName ] ?? null ) |
There was a problem hiding this comment.
There was a problem hiding this comment.
So we only getting layers from styles.elements so the resolver doesn't know about block's ancestors.
Yeah, that's a limitation of the current approach for sure. Not sure how well it'll work to walk up the block hierarchy to see what's there 🤔
Will poke at the idea tomorrow and make a call on whether we should go down the rabbithole now, or defer it to a future voyage!
There was a problem hiding this comment.
whether we should go down the rabbithole now, or defer it to a future voyage!
It is looking a bit hairy performing block lookups up the block hierarchy to make sure we're inheriting things correctly. My vote would be to leave blocks-within-blocks behaviour to a follow up and mark it as a task in the linked issue. What do you reckon?
There was a problem hiding this comment.
Agree. A follow up sounds best. Thanks for digging in.
getdave
left a comment
There was a problem hiding this comment.
I manually tested an number of scenarios and this worked as expected.
Noting @ramonjd's feedback about ancestor styles which will need to be resolved either here or in a follow up - will this be tracked somewhere?
As noted elsewhere I think we need some UI explanation about inherited styles other than a dotted line 😅 but I appreciate that's still in the works.
Great work here - this feature is a big win for the Editor 👏
Thanks @getdave. There are things coming out of the sausage factory on this point. Some suggested visual tweaks to the icons (#77894 (comment) and #80506). Aaron had a crack at tooltips, but I think that needs more attention in the next cycle as well as figuring out the trade off between UX and the components/design systems. |
|
+1 thanks for taking a look, Dave!
Agreed this should be looked into. My vote is to leave it for a follow-up and for us use the linked issue #80438 to track it. My gut feeling is that for 7.1 we won't have perfect coverage here, and I think the task will be to improve how this works iteratively across small PRs and see at what point the coverage feels "good enough". Which means, for now, is the coverage in this PR a good step forward, or does it feel too gappy? |
ramonjd
left a comment
There was a problem hiding this comment.
- Top level element values flow through to the inspector controls as advertised
- Switching heading levels updates the swatches
- Block-level global styles still win over element styles
As mentioned supporting paths like Group block > elements > h2 would be a nice follow up but I don't think it's a blocker here.
Nice work 🚀
LGTM ✅
| ### New Features | ||
|
|
||
| - Added a private `resolveStyle` API that resolves the merged Global Styles cascade (root, block type, and applied block style variation) for a block, returning the inherited value and a per-leaf source map. | ||
| - Added a private `resolveStyle` API that resolves the merged Global Styles cascade (root, root-level element layers, block type, and applied block style variation) for a block, returning the inherited value and a per-leaf source map. Element layers are supplied by the caller as an ordered `elements` list on the resolve context (low to high precedence, e.g. `[ 'heading', 'h2' ]`), keeping the engine agnostic of block-to-element mappings. |
There was a problem hiding this comment.
Added the PR to a separate changelog entry. I left the existing entries alone just in case it affects branch conflicts when we go to backport this (but I might be overthinking this one 😄)
| function mockStores( rawGlobalStyles, blockStyles = [] ) { | ||
| function mockStores( | ||
| rawGlobalStyles, | ||
| { blockStyles = [], attributes = {} } = {} |
There was a problem hiding this comment.
Can be later, but you do you think a test with { level: 2 } (or one with { level: 0 }) would catch a future regression in the path between useVariationAndElements and getElementLayers.
There was a problem hiding this comment.
We've already got a level: 2 so I've added one with level: 0, good catch!
Cheers! Yes, let's take a look in a follow-up and I'll jot down some notes in the linked issue. Thanks for the reviews! I'll merge this in once tests pass |
…ector controls (#80495) * Global Styles: resolve per-level heading element styles in inspector controls Completes the heading-family portion of the element inheritance layer tracked in #80438 (follow-up to #77894). The block inspector now reflects styles set on a specific heading level (`styles.elements.h1`-`h6`) in addition to the shared `heading` element. Previously the resolver folded in only `styles.elements.heading` for `core/heading`, so anything written by the per-level tabs in Styles > Typography > Headings was invisible to inspector controls. Because `fontSize` is deliberately disabled at the "All headings" level, every Global Styles heading font size lands in `elements.hN` and never reached a control at all. - Engine: replace the hardcoded `BLOCK_TO_ROOT_ELEMENT` map with an optional, caller-supplied `elements` list on the resolve context, ordered low to high precedence so `h2` wins over `heading`. This keeps the engine agnostic of block-to-element mappings and removes core block names from the package. The element list joins the memo cache key so two heading levels no longer share an entry. - block-editor: map block name + `level` to element keys for the heading family (`core/heading`, `site-title`, `post-title`, `query-title`, `comments-title`, `term-name`, `site-tagline`). A level of 0 (a block rendered as `<p>`) folds no heading layer. `clientId` is read from the block edit context, so `useResolvedStyle`'s signature is unchanged and no new store subscription is added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Update comment * Try to fix tests * Handle accordion heading * Add a test for the 0 heading level case, tidy up changelog --------- Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org>
|
I just cherry-picked this PR to the wp/7.1 branch to get it included in the next release: 26b39c0 |
|
Sharing for visibility; I'm considering removing the UI for global style inheritance from WP 7.1 and GB 23.6 releases, although it is not yet finalized. Please refer to #77894 (comment) for details. |
Oh, thanks for the heads-up @t-hamano! Do you want me to hold off on working on fixes like this for now? (My main interest is just in helping out with whatever's going to help with the release — whether that's trying to stabilize or fix things, or get out of your way 😄) |
|
I'm considering introducing the Gutenberg plugin check as I do not want to stop continuous development. See #77894 (comment) |
…lugin (#80555) * Global Styles: Gate the inherited value treatment on the plugin flag The inherited Global Styles treatment added in #77894 and #80495 lives in `block-editor`, which is synced to WordPress Core. Keep it to the Gutenberg plugin so Core builds keep showing locally-set values alone. `useResolvedStyle` resolves nothing when the flag is off, so each panel's `inheritedValue = value` default restores the pre-feature wiring, and the block-supports panels default `showInheritanceLabelIndicators` to the same flag, switching off every affordance routed through `getInheritanceProps`. Both are required: gating only the value leaves `inheritedValue === value`, which reads as a local override on every locally-set control and renders a reset dot. The typography panel's link-color sync reads `inheritedValue` outside that prop, and collapsing it onto `value` would write a link color where trunk wrote none, so it falls back to the pre-feature comparison when the flag is off. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Note why the inheritance gate returns early Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Add the PR number to the changelog entry Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Restore comment on inheritance className gating The comment documented a bug found in the original implementation: the layout className must always be passed through, and only the inheritance treatment is gated on `showInheritanceLabelIndicators`. Dropping it loses that context since the code itself is unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Cover the Core path of ENABLE_GLOBAL_STYLES_INHERITANCE The unit test environment sets `IS_GUTENBERG_PLUGIN` to true, so every existing test exercises the plugin branch only. Nothing guarded the Core behaviour the flag is meant to preserve, which is the behaviour that ships to WordPress. Add two files that mock the constant to false. `jest.mock` is file-scoped, so they cannot live alongside the plugin-path tests. - `useResolvedStyle` resolves nothing, so the panels fall back to their `inheritedValue = value` default and Core shows locally-set values only. - `TypographyPanel` applies no inherited treatment and no reset dot by default, and its link colour sync falls back to comparing the local pair, which is what Core did before the inheritance treatment landed. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Compare inherited values in the Core link colour sync The Core fallback compared `value`, but the check this replaced compared `inheritedValue`. The two are only the same in the block inspector, where `useResolvedStyle` resolves nothing and the prop falls back to `value`. In Global Styles they diverge: `value` is the user config and `inheritedValue` is the merged config. Comparing `value` there meant a theme defining a mismatched text and link colour pair would still sync the link colour, because both sides of the comparison were undefined until the user set something. Restore the original comparison, which is correct on both paths. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Guard the Core link colour sync against reading the user config The existing link colour tests all render without an `inheritedValue`, the block inspector shape where the prop falls back to `value`. On that path the two configs are identical, so none of them notice if the comparison switches from `inheritedValue` to `value`. Add a case with the divergent Global Styles shape: an empty user config and a merged config whose text and link colours differ. Reading `value` there finds undefined on both sides and syncs, which the assertion catches. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
…lugin (#80555) * Global Styles: Gate the inherited value treatment on the plugin flag The inherited Global Styles treatment added in #77894 and #80495 lives in `block-editor`, which is synced to WordPress Core. Keep it to the Gutenberg plugin so Core builds keep showing locally-set values alone. `useResolvedStyle` resolves nothing when the flag is off, so each panel's `inheritedValue = value` default restores the pre-feature wiring, and the block-supports panels default `showInheritanceLabelIndicators` to the same flag, switching off every affordance routed through `getInheritanceProps`. Both are required: gating only the value leaves `inheritedValue === value`, which reads as a local override on every locally-set control and renders a reset dot. The typography panel's link-color sync reads `inheritedValue` outside that prop, and collapsing it onto `value` would write a link color where trunk wrote none, so it falls back to the pre-feature comparison when the flag is off. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Note why the inheritance gate returns early Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Add the PR number to the changelog entry Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Restore comment on inheritance className gating The comment documented a bug found in the original implementation: the layout className must always be passed through, and only the inheritance treatment is gated on `showInheritanceLabelIndicators`. Dropping it loses that context since the code itself is unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Cover the Core path of ENABLE_GLOBAL_STYLES_INHERITANCE The unit test environment sets `IS_GUTENBERG_PLUGIN` to true, so every existing test exercises the plugin branch only. Nothing guarded the Core behaviour the flag is meant to preserve, which is the behaviour that ships to WordPress. Add two files that mock the constant to false. `jest.mock` is file-scoped, so they cannot live alongside the plugin-path tests. - `useResolvedStyle` resolves nothing, so the panels fall back to their `inheritedValue = value` default and Core shows locally-set values only. - `TypographyPanel` applies no inherited treatment and no reset dot by default, and its link colour sync falls back to comparing the local pair, which is what Core did before the inheritance treatment landed. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Compare inherited values in the Core link colour sync The Core fallback compared `value`, but the check this replaced compared `inheritedValue`. The two are only the same in the block inspector, where `useResolvedStyle` resolves nothing and the prop falls back to `value`. In Global Styles they diverge: `value` is the user config and `inheritedValue` is the merged config. Comparing `value` there meant a theme defining a mismatched text and link colour pair would still sync the link colour, because both sides of the comparison were undefined until the user set something. Restore the original comparison, which is correct on both paths. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Guard the Core link colour sync against reading the user config The existing link colour tests all render without an `inheritedValue`, the block inspector shape where the prop falls back to `value`. On that path the two configs are identical, so none of them notice if the comparison switches from `inheritedValue` to `value`. Add a case with the divergent Global Styles shape: an empty user config and a merged config whose text and link colours differ. Reading `value` there finds undefined on both sides and syncs, which the assertion catches. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
…ector controls (#80495) * Global Styles: resolve per-level heading element styles in inspector controls Completes the heading-family portion of the element inheritance layer tracked in #80438 (follow-up to #77894). The block inspector now reflects styles set on a specific heading level (`styles.elements.h1`-`h6`) in addition to the shared `heading` element. Previously the resolver folded in only `styles.elements.heading` for `core/heading`, so anything written by the per-level tabs in Styles > Typography > Headings was invisible to inspector controls. Because `fontSize` is deliberately disabled at the "All headings" level, every Global Styles heading font size lands in `elements.hN` and never reached a control at all. - Engine: replace the hardcoded `BLOCK_TO_ROOT_ELEMENT` map with an optional, caller-supplied `elements` list on the resolve context, ordered low to high precedence so `h2` wins over `heading`. This keeps the engine agnostic of block-to-element mappings and removes core block names from the package. The element list joins the memo cache key so two heading levels no longer share an entry. - block-editor: map block name + `level` to element keys for the heading family (`core/heading`, `site-title`, `post-title`, `query-title`, `comments-title`, `term-name`, `site-tagline`). A level of 0 (a block rendered as `<p>`) folds no heading layer. `clientId` is read from the block edit context, so `useResolvedStyle`'s signature is unchanged and no new store subscription is added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Update comment * Try to fix tests * Handle accordion heading * Add a test for the 0 heading level case, tidy up changelog --------- Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org>
…lugin (#80555) * Global Styles: Gate the inherited value treatment on the plugin flag The inherited Global Styles treatment added in #77894 and #80495 lives in `block-editor`, which is synced to WordPress Core. Keep it to the Gutenberg plugin so Core builds keep showing locally-set values alone. `useResolvedStyle` resolves nothing when the flag is off, so each panel's `inheritedValue = value` default restores the pre-feature wiring, and the block-supports panels default `showInheritanceLabelIndicators` to the same flag, switching off every affordance routed through `getInheritanceProps`. Both are required: gating only the value leaves `inheritedValue === value`, which reads as a local override on every locally-set control and renders a reset dot. The typography panel's link-color sync reads `inheritedValue` outside that prop, and collapsing it onto `value` would write a link color where trunk wrote none, so it falls back to the pre-feature comparison when the flag is off. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Note why the inheritance gate returns early Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Add the PR number to the changelog entry Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Restore comment on inheritance className gating The comment documented a bug found in the original implementation: the layout className must always be passed through, and only the inheritance treatment is gated on `showInheritanceLabelIndicators`. Dropping it loses that context since the code itself is unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Cover the Core path of ENABLE_GLOBAL_STYLES_INHERITANCE The unit test environment sets `IS_GUTENBERG_PLUGIN` to true, so every existing test exercises the plugin branch only. Nothing guarded the Core behaviour the flag is meant to preserve, which is the behaviour that ships to WordPress. Add two files that mock the constant to false. `jest.mock` is file-scoped, so they cannot live alongside the plugin-path tests. - `useResolvedStyle` resolves nothing, so the panels fall back to their `inheritedValue = value` default and Core shows locally-set values only. - `TypographyPanel` applies no inherited treatment and no reset dot by default, and its link colour sync falls back to comparing the local pair, which is what Core did before the inheritance treatment landed. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Compare inherited values in the Core link colour sync The Core fallback compared `value`, but the check this replaced compared `inheritedValue`. The two are only the same in the block inspector, where `useResolvedStyle` resolves nothing and the prop falls back to `value`. In Global Styles they diverge: `value` is the user config and `inheritedValue` is the merged config. Comparing `value` there meant a theme defining a mismatched text and link colour pair would still sync the link colour, because both sides of the comparison were undefined until the user set something. Restore the original comparison, which is correct on both paths. Co-Authored-By: Claude <noreply@anthropic.com> * Global Styles: Guard the Core link colour sync against reading the user config The existing link colour tests all render without an `inheritedValue`, the block inspector shape where the prop falls back to `value`. On that path the two configs are identical, so none of them notice if the comparison switches from `inheritedValue` to `value`. Add a case with the divergent Global Styles shape: an empty user config and a merged config whose text and link colours differ. Reading `value` there finds undefined on both sides and syncs, which the assertion catches. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
|
I just cherry-picked this PR to the release/23.6 branch to get it included in the next release: 6cd4ef0 |
This updates the pinned commit hash of the Gutenberg repository from `e73c3c481db0650183f092af157f6e42efe9ee2d` to `4997026b75c922d8a6f77a03d72ed7cad04c7073`. A full list of changes included in this commit can be found on GitHub: WordPress/gutenberg@e73c3c4...4997026 - Notes: Replace blur-deselect bookkeeping with useFocusOutside (WordPress/gutenberg#80222) - Playlist: Update @SInCE tags to 7.1.0 (WordPress/gutenberg#80317) - fix playlist block Dimensions Design (WordPress/gutenberg#80312) - UI: Backport compat overlay fixes to WordPress 7.1 (WordPress/gutenberg#80322) - Editor: allow selecting which block styles to apply globally (WordPress/gutenberg#79839) - Global Styles: Reject non-string custom CSS in the REST controller (WordPress/gutenberg#80338) - Open inspector sidebar when toggling responsive editing (WordPress/gutenberg#80307) - Client Side Media: Honor image_strip_meta and image_max_bit_depth on the client upload path (WordPress/gutenberg#80218) - Hide block style variations when state is enabled in global styles (WordPress/gutenberg#80341) - Media REST API: Fix sideload and finalize for EXIF rotated images (WordPress/gutenberg#80295) - Fix upload snackbar stuck in uploading state on server-side uploads (WordPress/gutenberg#80345) - Try fixing responsive layout in Nav block (WordPress/gutenberg#80305) - Responsive styles: Use viewport dropdown to control states for in-editor global styles sidebar (WordPress/gutenberg#80339) - RichTextControl: Replace DOM focus tracking with a single React-tree focus boundary (WordPress/gutenberg#80324) - Notes: Finish WPDS treatment for mention chips (WordPress/gutenberg#80300) - Notes: Add placeholders to the RichText fields (WordPress/gutenberg#80296) - Fix upload hang when converting long animated GIFs: decode only the first frame for still outputs (WordPress/gutenberg#80260) (WordPress/gutenberg#80342) - Device preview dropdown: use active color for device icon when responsive styles are active (WordPress/gutenberg#80346) - Fix default aspect ratio for lazy loaded Featured image (WordPress/gutenberg#80386) - Vips/upload-media: consolidate optional params into options objects (WordPress/gutenberg#80330) - Autocompleters: Don't pre-encode mention search terms (WordPress/gutenberg#80377) - Animated GIF uploads: generate sub-sizes from the first frame, matching core (WordPress/gutenberg#80268) - Custom CSS: Fix cascade order against block style variations (WordPress/gutenberg#80340) - Rich Text: Restore the selection when focus returns to the editable (WordPress/gutenberg#80396) - Notes: Arm the mention kses allowance on REST note creation (WordPress/gutenberg#80221) - Fix upload snackbar double-counting a single HEIC upload in Safari (WordPress/gutenberg#80436) - ContentEditableControl: fix invalid label association with contenteditable div (WordPress/gutenberg#80441) - Editor: Disable canvas resizing while zoomed out (WordPress/gutenberg#80391) - Fix Color Picker Cursor Shaking Issue (WordPress/gutenberg#80205) (WordPress/gutenberg#80435) - Misc fixes for WordPress-Develop 7.0 merges (WordPress/gutenberg#80444) - Style Book: Restore live global styles updates on the styles route (WordPress/gutenberg#80459) - Worker threads: reject pending RPC calls on worker failure or termination (WordPress/gutenberg#79955) (WordPress/gutenberg#80421) - Media: Add timeout and size guardrails to client-side GIF to video conversion (WordPress/gutenberg#80420) - Post Content: Use the default block appender for empty content (WordPress/gutenberg#80026) - Block Supports: Handle nested array block gap values properly (WordPress/gutenberg#80464) - Editor: Restore fixed device preview height for mobile and tablet (WordPress/gutenberg#80466) - Block Editor: Guard against non-string spacing preset values (WordPress/gutenberg#80467) - Writing flow: fully select the ancestor when a text selection crosses a nesting boundary (WordPress/gutenberg#80462) - Block Editor: Reflect inherited Global Styles values in block inspector controls (WordPress/gutenberg#80481) - Autocomplete: Reference the suggestions list with `aria-controls` and `aria-haspopup` (WordPress/gutenberg#80403) (WordPress/gutenberg#80499) - Media: Remove the redundant __heicUploadSupport flag (WordPress/gutenberg#80486) - State control - avoid tertiary variant on toggle to match style of other dropdown toggles (WordPress/gutenberg#80505) - Icons: Store the sanitized SVG content when registering an icon (WordPress/gutenberg#80508) - Fix `useHomeEnd` on tabs in mac testing (WordPress/gutenberg#80374) - Playlist: Fix playback of tracks served without CORS headers (WordPress/gutenberg#80533) - Redirect editing events to extension handlers under editableRoot (WordPress/gutenberg#80287) - Writing flow: fully select the items when a selection extends down into a nested item (WordPress/gutenberg#80492) - Global Styles panels: fix wrong preset committed and shown when two color presets share a hex (WordPress/gutenberg#80497) - Replaces the `title` attributes used by revision inline diff annotations with `aria-describedby` (WordPress/gutenberg#80440) - Notes: Remove "Add note" from the inline styles dropdown (WordPress/gutenberg#80531) - Global Styles: Resolve per-level heading element styles in block inspector controls (WordPress/gutenberg#80495) - Notes: Render @ mentions as span chips and narrow the kses class allowance (WordPress/gutenberg#80528) - Revisions: Specify block level diff status via aria-label (WordPress/gutenberg#77779) - Backport from Core: improve icon name unit tests (WordPress/gutenberg#80552) - Device type preview: fix collapsing to content height (WordPress/gutenberg#80553) - Wrap notices in ThemeProvider with 0 corner radius (WordPress/gutenberg#80557) - Global Styles: Limit the inherited value treatment to the Gutenberg plugin (WordPress/gutenberg#80555) - Fix crashes when manipulating locked blocks (WordPress/gutenberg#80509) - Notes: align floating threads with their inline marker (WordPress/gutenberg#79877) Props wildworks. See #65529. git-svn-id: https://develop.svn.wordpress.org/trunk@62824 602fd350-edb4-49c9-b593-d223f7449a82
This updates the pinned commit hash of the Gutenberg repository from `e73c3c481db0650183f092af157f6e42efe9ee2d` to `4997026b75c922d8a6f77a03d72ed7cad04c7073`. A full list of changes included in this commit can be found on GitHub: WordPress/gutenberg@e73c3c4...4997026 - Notes: Replace blur-deselect bookkeeping with useFocusOutside (WordPress/gutenberg#80222) - Playlist: Update @SInCE tags to 7.1.0 (WordPress/gutenberg#80317) - fix playlist block Dimensions Design (WordPress/gutenberg#80312) - UI: Backport compat overlay fixes to WordPress 7.1 (WordPress/gutenberg#80322) - Editor: allow selecting which block styles to apply globally (WordPress/gutenberg#79839) - Global Styles: Reject non-string custom CSS in the REST controller (WordPress/gutenberg#80338) - Open inspector sidebar when toggling responsive editing (WordPress/gutenberg#80307) - Client Side Media: Honor image_strip_meta and image_max_bit_depth on the client upload path (WordPress/gutenberg#80218) - Hide block style variations when state is enabled in global styles (WordPress/gutenberg#80341) - Media REST API: Fix sideload and finalize for EXIF rotated images (WordPress/gutenberg#80295) - Fix upload snackbar stuck in uploading state on server-side uploads (WordPress/gutenberg#80345) - Try fixing responsive layout in Nav block (WordPress/gutenberg#80305) - Responsive styles: Use viewport dropdown to control states for in-editor global styles sidebar (WordPress/gutenberg#80339) - RichTextControl: Replace DOM focus tracking with a single React-tree focus boundary (WordPress/gutenberg#80324) - Notes: Finish WPDS treatment for mention chips (WordPress/gutenberg#80300) - Notes: Add placeholders to the RichText fields (WordPress/gutenberg#80296) - Fix upload hang when converting long animated GIFs: decode only the first frame for still outputs (WordPress/gutenberg#80260) (WordPress/gutenberg#80342) - Device preview dropdown: use active color for device icon when responsive styles are active (WordPress/gutenberg#80346) - Fix default aspect ratio for lazy loaded Featured image (WordPress/gutenberg#80386) - Vips/upload-media: consolidate optional params into options objects (WordPress/gutenberg#80330) - Autocompleters: Don't pre-encode mention search terms (WordPress/gutenberg#80377) - Animated GIF uploads: generate sub-sizes from the first frame, matching core (WordPress/gutenberg#80268) - Custom CSS: Fix cascade order against block style variations (WordPress/gutenberg#80340) - Rich Text: Restore the selection when focus returns to the editable (WordPress/gutenberg#80396) - Notes: Arm the mention kses allowance on REST note creation (WordPress/gutenberg#80221) - Fix upload snackbar double-counting a single HEIC upload in Safari (WordPress/gutenberg#80436) - ContentEditableControl: fix invalid label association with contenteditable div (WordPress/gutenberg#80441) - Editor: Disable canvas resizing while zoomed out (WordPress/gutenberg#80391) - Fix Color Picker Cursor Shaking Issue (WordPress/gutenberg#80205) (WordPress/gutenberg#80435) - Misc fixes for WordPress-Develop 7.0 merges (WordPress/gutenberg#80444) - Style Book: Restore live global styles updates on the styles route (WordPress/gutenberg#80459) - Worker threads: reject pending RPC calls on worker failure or termination (WordPress/gutenberg#79955) (WordPress/gutenberg#80421) - Media: Add timeout and size guardrails to client-side GIF to video conversion (WordPress/gutenberg#80420) - Post Content: Use the default block appender for empty content (WordPress/gutenberg#80026) - Block Supports: Handle nested array block gap values properly (WordPress/gutenberg#80464) - Editor: Restore fixed device preview height for mobile and tablet (WordPress/gutenberg#80466) - Block Editor: Guard against non-string spacing preset values (WordPress/gutenberg#80467) - Writing flow: fully select the ancestor when a text selection crosses a nesting boundary (WordPress/gutenberg#80462) - Block Editor: Reflect inherited Global Styles values in block inspector controls (WordPress/gutenberg#80481) - Autocomplete: Reference the suggestions list with `aria-controls` and `aria-haspopup` (WordPress/gutenberg#80403) (WordPress/gutenberg#80499) - Media: Remove the redundant __heicUploadSupport flag (WordPress/gutenberg#80486) - State control - avoid tertiary variant on toggle to match style of other dropdown toggles (WordPress/gutenberg#80505) - Icons: Store the sanitized SVG content when registering an icon (WordPress/gutenberg#80508) - Fix `useHomeEnd` on tabs in mac testing (WordPress/gutenberg#80374) - Playlist: Fix playback of tracks served without CORS headers (WordPress/gutenberg#80533) - Redirect editing events to extension handlers under editableRoot (WordPress/gutenberg#80287) - Writing flow: fully select the items when a selection extends down into a nested item (WordPress/gutenberg#80492) - Global Styles panels: fix wrong preset committed and shown when two color presets share a hex (WordPress/gutenberg#80497) - Replaces the `title` attributes used by revision inline diff annotations with `aria-describedby` (WordPress/gutenberg#80440) - Notes: Remove "Add note" from the inline styles dropdown (WordPress/gutenberg#80531) - Global Styles: Resolve per-level heading element styles in block inspector controls (WordPress/gutenberg#80495) - Notes: Render @ mentions as span chips and narrow the kses class allowance (WordPress/gutenberg#80528) - Revisions: Specify block level diff status via aria-label (WordPress/gutenberg#77779) - Backport from Core: improve icon name unit tests (WordPress/gutenberg#80552) - Device type preview: fix collapsing to content height (WordPress/gutenberg#80553) - Wrap notices in ThemeProvider with 0 corner radius (WordPress/gutenberg#80557) - Global Styles: Limit the inherited value treatment to the Gutenberg plugin (WordPress/gutenberg#80555) - Fix crashes when manipulating locked blocks (WordPress/gutenberg#80509) - Notes: align floating threads with their inline marker (WordPress/gutenberg#79877) Props wildworks. See #65529. Built from https://develop.svn.wordpress.org/trunk@62824 git-svn-id: http://core.svn.wordpress.org/trunk@62104 1a063a9b-81f0-0310-95a4-ce76da25c4cd

Part of:
Follows:
What?
Resolve per-level heading element styles in the block inspector style inheritance logic.
Note: I haven't touched
linkstyles yet as I'm trying to keep this fairly contained while getting up to speed on the feature.Why?
The was a noted gap in the big global styles inheritance PR and an intended follow-up. It allows Heading blocks (or those that use heading elements) to more accurately reflect inherited colors and styles in the block inspector sidebar, i.e. those values that are set at an individual heading level in global styles (e.g. h2) rather than at the root (heading) level.
How?
Basically, attempt to implement the ideas that Aaron raised in #80438 for adding in this elements layer. Any errors in the approach here are likely mine as I attempt to get up to speed with how this is hooked together. Broadly:
elementsas a prop (it's up to the caller to specify for the different blocks)headingLevelfrom block attributes (via the clientId retrieved from blockEdit context) so that we can grab the right element layers to pass along toresolveStyle— in my mind this is the main "bit" of this PR as it's where we tell the resolver which heading level we're using for this particular blockresolveStylecontext object to accept anelementsarray so that the caller can pass in a low-to-high hierarchy of elements used by the block. While this is different to the other props, in that it's an array instead of a single value, I think it has to be an array because for headings we haveheadingand a specific heading value likeh2Testing Instructions
To be thorough, test with the following core blocks:
Heading blocks:
Screenshots or screencast
Setting some styling rules at the numbered heading level in Global Styles > Headings elements > Typography
Then, when you're in a post and you add a heading block of the appropriate level, the controls should pick up that inherited value (they don't on
trunk):2026-07-21.14.49.45.mp4
Use of AI Tools
Claude Code