Skip to content

Colour: Add a PHP helper for block support classes and styles - #84206

Merged
aaronrobertshaw merged 16 commits into
trunkfrom
update/color-classes-and-styles-php-helper
Nov 4, 2026
Merged

aaronrobertshaw merged 16 commits into
trunkfrom
update/color-classes-and-styles-php-helper

Conversation

@aaronrobertshaw

@aaronrobertshaw aaronrobertshaw commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Follows up on #83122.
Core backport: wordpress-develop#14094.

What?

Adds a shared PHP helper that turns a block's color attributes into classes and inline styles, the PHP version of the JS getColorClassesAndStyles().

wp_get_color_classes_and_styles( $block_attributes );
// array( 'class' => 'has-text-color has-contrast-color has-background has-base-background-color', ... )

The color block support and Calendar now use it.

Why?

Calendar skips color serialization so it can put its colors on the table. It copies the block support's text and background logic to do so. A shared helper keeps the two in step.

How?

The helper only builds output. It doesn't check what a block supports, so each caller passes in the values it applies.

  • Color block support: keeps all its checks, then calls the helper
  • Calendar: text and background only, keeps its has-link-color class
  • Build: added to prefixFunctions, so the plugin calls gutenberg_get_color_classes_and_styles()

The only output change: a null, false, empty or zero preset attribute now falls back to the custom color, as in JS. So does an array, which cannot form a class name.

PHPStan's WordPress stubs are built from Core trunk, which won't have this helper until wordpress-develop#14094 lands. So this PR adds a temporary baseline entry for it. PHPStan will flag the entry for removal once the stubs move to a Core trunk with the helper.

Testing Instructions

  1. Add Calendar blocks with preset colors, custom colors with a link color, and no colors.
  2. Compare the front end table markup with trunk. It should match.
  3. Add a Group with text, background and gradient colors. It renders as on trunk.

Use of AI Tools

Implemented and tested by a Claude Code agent from a predefined task.

@aaronrobertshaw aaronrobertshaw added [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Type] Enhancement A suggestion for improvement. [Package] Block library /packages/block-library labels Oct 8, 2026
@aaronrobertshaw aaronrobertshaw self-assigned this Oct 8, 2026
@aaronrobertshaw aaronrobertshaw added the Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json label Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

🎉 Props

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: aaronrobertshaw <aaronrobertshaw@git.wordpress.org>
Co-authored-by: westonruter <westonruter@git.wordpress.org>
Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>

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


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

Updated as activity occurs, without notifying anyone named here. Add the props-bot label to refresh.

📦 Bundle size

Size Change: 0 B

Total Size: 8.61 MB

8130a1d Run

⚡ Performance

Show the results

Client side metrics exclude the server response time.

front-end-block-theme

Metric 376d9d0 trunk % Change
timeToFirstByte 43.85 ms +5.82% -5.93% 43.3 ms +17.55% -4.5% 1.27%
largestContentfulPaint 74 ms +5.41% -5.41% 72 ms +11.11% -2.78% 2.78%
lcpMinusTtfb 28 ms +21.61% -2.14% 28.4 ms +4.58% -3.35% -1.41%
wpBeforeTemplate 22.53 ms +14.29% -3.42% 22.17 ms +20.79% -2.75% 1.62%
wpTemplate 16.99 ms +5% -4.47% 17.2 ms +3.49% -5.47% -1.22%
wpTotal 40.39 ms +6.19% -5.6% 39.97 ms +15.46% -4.58% 1.05%
wpMemoryUsage 7.72 MB +0% -0% 7.68 MB +0% -0% 0.43%
wpDbQueries 16 +0% -0% 16 +0% -0% 0%

front-end-classic-theme

Metric 376d9d0 trunk % Change
timeToFirstByte 35.1 ms +4.27% -1.71% 32.25 ms +6.36% -3.88% 8.84%
largestContentfulPaint 80 ms +0% -2.5% 72 ms +0% -5.56% 11.11%
lcpMinusTtfb 43.65 ms +3.21% -4.12% 38.75 ms +3.74% -3.74% 12.65%
wpBeforeTemplate 19.23 ms +2.44% -1.61% 19.15 ms +9.87% -0.73% 0.42%
wpTemplate 13.09 ms +4.89% -3.59% 9.9 ms +2.53% -6.06% 32.22%
wpTotal 32.47 ms +4.53% -2.03% 29.46 ms +6.59% -3.05% 10.22%
wpMemoryUsage 6.41 MB +0% -0% 6.26 MB +0% -0% 2.32%
wpDbQueries 13 +0% -0% 9 +0% -0% 44.44%

media-processing

Metric 376d9d0 trunk % Change
mediaProcessingJpeg 325.32 ms +0.6% -1.24% 324.25 ms +2% -0.8% 0.33%
mediaProcessingAvif 4833.57 ms +0.49% -0.15% 4835.37 ms +0.34% -0.33% -0.04%
mediaProcessingJpegToAvif 3386.66 ms +0.61% -0.28% 3394.6 ms +0.14% -0.49% -0.23%

media-upload

Metric 376d9d0 trunk % Change
jpegUploadProcessing 1428.39 ms +1.32% -1.49% 1415.87 ms +0.29% -0.58% 0.88%
pngUploadProcessing 221.95 ms +3.73% -5.24% 206.96 ms +1.97% -3.42% 7.24%
largeJpegUploadProcessing 1423.51 ms +0.28% -1.21% 1417.63 ms +1.58% -0.89% 0.41%
multipleImageUploadProcessing 1471.58 ms +1.85% -0.33% 1477.12 ms +0.49% -0.97% -0.38%

post-editor

Metric 376d9d0 trunk % Change
serverResponse 263 ms +2.93% -10.87% 239.74 ms +15.25% -1.34% 9.7%
firstPaint 295.51 ms +14.76% -42.15% 270.35 ms +22.4% -14.8% 9.31%
domContentLoaded 562.53 ms +2.28% -2.54% 563.26 ms +4.4% -1.56% -0.13%
loaded 563.33 ms +2.28% -2.57% 563.96 ms +4.41% -1.56% -0.11%
firstContentfulPaint 332.94 ms +4.02% -2.05% 334.2 ms +4.08% -1.19% -0.38%
firstBlock 1401.92 ms +3.75% -1.73% 1412.24 ms +1.31% -1.37% -0.73%
type 13.19 ms +15.39% -14.03% 12.89 ms +5.35% -9.08% 2.33%
typeWithoutInspector 12.8 ms +2.19% -8.28% 12.25 ms +13.47% -8.08% 4.49%
typeWithTopToolbar 16.08 ms +3.23% -9.27% 15.46 ms +6.53% -7.5% 4.01%
typeContainer 6.01 ms +14.48% -11.81% 6.25 ms +15.04% -9.44% -3.84%
focus 74.79 ms +2.23% -5.11% 70.22 ms +4.67% -3.59% 6.51%
firstFocus 146.32 ms +0% -0% 163.88 ms +0% -0% -10.72%
selectAll 240.64 ms +1.25% -0.78% 246.08 ms +2.55% -1.13% -2.21%
undo 18.68 ms +8.51% -3.27% 21.01 ms +6.57% -7% -11.09%
listViewOpen 46.59 ms +2.64% -5.6% 45.61 ms +5.24% -3.64% 2.15%
inserterOpen 27.12 ms +7.01% -3.95% 27.81 ms +6.94% -3.56% -2.48%
inserterHover 8.03 ms +3.86% -6.48% 8.03 ms +9.46% -4.48% 0%
inserterSearch 6.5 ms +4.92% -6% 6.37 ms +7.22% -7.38% 2.04%
loadPatterns 424.35 ms +4.85% -1.57% 422.06 ms +3.7% -1.9% 0.54%
wpTotal 256.01 ms +2.7% -11.19% 232.86 ms +15.22% -1.42% 9.94%
wpMemoryUsage 14.76 MB +0% -0% 14.73 MB +0% -0% 0.24%
wpDbQueries 55 +0% -0% 55 +0% -0% 0%

site-editor

Metric 376d9d0 trunk % Change
serverResponse 256.5 ms +4.25% -8.52% 253.44 ms +5.59% -5.67% 1.21%
firstPaint 252.36 ms +5.04% -9.93% 258.24 ms +2.37% -7.86% -2.28%
domContentLoaded 583.96 ms +4.49% -2.1% 585.68 ms +7.36% -1.93% -0.29%
loaded 584.75 ms +4.49% -2.12% 586.35 ms +7.39% -1.86% -0.27%
firstContentfulPaint 340.46 ms +4.62% -1.59% 344.95 ms +5.5% -2.56% -1.3%
firstBlock 1697.04 ms +5.98% -0.54% 1706.83 ms +3.27% -2.03% -0.57%
type 12.74 ms +8.24% -3.77% 12.06 ms +14.18% -4.06% 5.64%
navigate 82.58 ms +7.47% -5.32% 79.15 ms +3.77% -5.87% 4.33%
loadPatterns 996.35 ms +8.45% -5.72% 915.78 ms +6.39% -17.23% 8.8%
loadPages 931.9 ms +2.96% -0.57% 935.19 ms +3.58% -1.09% -0.35%
wpTotal 249.9 ms +2.43% -8.83% 247.05 ms +5.66% -5.87% 1.15%
wpMemoryUsage 12.78 MB +0% -0% 12.74 MB +0% -0% 0.27%
wpDbQueries 45 +0% -0% 45 +0% -0% 0%

8130a1d Run

🏁 Flaky tests

Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

Undo restores the post selection when another synced entity is loaded (RTC WebSocket) in /test/e2e/specs/editor/collaboration/collaboration-undo-redo.spec.ts, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 2
+ Received  + 2

  Object {
    "attributeKey": "content",
    "blockIndex": 0,
    "content": "abcdef",
-   "endOffset": 3,
-   "offset": 3,
+   "endOffset": 6,
+   "offset": 6,
  }

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/collaboration/collaboration-undo-redo.spec.ts:363:5
Undo restores the post selection when another synced entity is loaded in /test/e2e/specs/editor/collaboration/collaboration-undo-redo.spec.ts, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 2
+ Received  + 2

  Object {
    "attributeKey": "content",
    "blockIndex": 0,
    "content": "abcdef",
-   "endOffset": 3,
-   "offset": 3,
+   "endOffset": 6,
+   "offset": 6,
  }

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/collaboration/collaboration-undo-redo.spec.ts:363:5
a navigation superseded by the traversal discharges to idle in /test/e2e/specs/interactivity/router-navigation-lifecycle.spec.ts, passed after 1 failed attempt.
SyntaxError: Unexpected token 'o', "not hydrated" is not valid JSON
    at readLog (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/interactivity/router-navigation-lifecycle.spec.ts:28:14)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/interactivity/router-navigation-lifecycle.spec.ts:47:24
    at waitForLogLength (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/interactivity/router-navigation-lifecycle.spec.ts:46:2)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/interactivity/router-navigation-lifecycle.spec.ts:693:5
can update custom URL link to a new custom URL link in /test/e2e/specs/editor/blocks/navigation.spec.js, passed after 1 failed attempt.
Error: apiRequestContext.fetch: socket hang up
Call log:
  - → DELETE http://localhost:8889/wp-json/wp/v2/pages/52?force=true
    - user-agent: Playwright/1.63.0 (x64; ubuntu 24.04) node/24.20 CI/1
    - accept: */*
    - accept-encoding: gzip,deflate,br
    - X-WP-Nonce: 4c153f3cb6
    - cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_23778236db82f19306f247e20a353a99=admin%7C1793971850%7CjVVblZA7kxILfhe1jhRgdwSLqQqZ0hkraXRWcSd2TY1%7C8a7e0707d6a7e7501a8a7e31abe0eb1fc3b39d9548b4a45d56c8ad2562e18614; wp-settings-time-1=1793799089

    at RequestUtils.rest (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/rest.ts:111:39)
    at RequestUtils.call (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/pages.ts:27:20)
    at map (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/pages.ts:56:37)
    at RequestUtils.deleteAllPages (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/pages.ts:56:9)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/blocks/navigation.spec.js:2361:4

8130a1d Run

@aaronrobertshaw
aaronrobertshaw force-pushed the update/color-classes-and-styles-php-helper branch 2 times, most recently from 871f822 to 30eecbf Compare October 8, 2026 05:56
@aaronrobertshaw aaronrobertshaw added [Type] Code Quality Issues or PRs that relate to code quality and removed [Type] Enhancement A suggestion for improvement. Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json labels Oct 8, 2026
@aaronrobertshaw
aaronrobertshaw force-pushed the update/color-classes-and-styles-php-helper branch from 39ad58f to 884c378 Compare October 8, 2026 12:11
@aaronrobertshaw
aaronrobertshaw force-pushed the update/color-classes-and-styles-php-helper branch 3 times, most recently from 7ead1ca to 0c0ad39 Compare October 20, 2026 05:29
@aaronrobertshaw
aaronrobertshaw marked this pull request as ready for review October 21, 2026 11:19
@aaronrobertshaw
aaronrobertshaw force-pushed the update/color-classes-and-styles-php-helper branch 2 times, most recently from 5157112 to ebd42f6 Compare October 27, 2026 07:52

@ramonjd ramonjd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the follow-up.

In my testing, the calendar block uses the same color code as the block support instead of keeping its own copy, and the output matches trunk in my testing.

Just left a couple of questions about the numeric checks on the slugs. Not sure if they're required?

Comment thread lib/block-supports/colors.php Resolved
Comment thread backport-changelog/7.3/14094.md Resolved
@aaronrobertshaw
aaronrobertshaw force-pushed the update/color-classes-and-styles-php-helper branch 2 times, most recently from c94e83f to a4e7ab4 Compare November 2, 2026 02:58
@aaronrobertshaw

Copy link
Copy Markdown
Contributor Author

Thanks for the reviews @ramonjd 👍

I've addressed the feedback to date and applied some of that across all the PHP block support helper PRs I have open.

PHPStan also landed on trunk this week and doesn't know the new helper yet since it isn't in Core until WordPress/wordpress-develop#14094. So I've added a temporary baseline entry for it.

I'll look to get these PRs merged and juggle the rebases needed for that today and tomorrow.

@aaronrobertshaw
aaronrobertshaw force-pushed the update/color-classes-and-styles-php-helper branch from bcda3fa to aade5ad Compare November 4, 2026 03:56
Comment thread tools/phpstan/baseline.neon Resolved
aaronrobertshaw and others added 16 commits November 4, 2026 21:17
Theme.json slugs are strings and the editor always coerces them, so the
numeric and boolean handling only added code.
The block library calls wp_get_color_classes_and_styles(), which the
build prefixes to gutenberg_get_color_classes_and_styles() for the
plugin, but which PHPStan resolves from the WordPress stubs. The stubs
were generated from core trunk, which lacks the function, so its call
was baselined as not found.

Generate the stubs from wordpress-develop PR 14094, which backports the
helper, and drop the baselined error. Regenerate them from trunk once
the backport is committed.

Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: cfcf15e8-ccc1-4d78-a7c9-51f73e8e4b92
@aaronrobertshaw
aaronrobertshaw force-pushed the update/color-classes-and-styles-php-helper branch from fa4a46a to 8130a1d Compare November 4, 2026 13:24
@aaronrobertshaw
aaronrobertshaw merged commit 6ec1ae1 into trunk Nov 4, 2026
84 checks passed
@aaronrobertshaw
aaronrobertshaw deleted the update/color-classes-and-styles-php-helper branch November 4, 2026 14:14
@github-actions github-actions Bot added this to the Gutenberg 24.5 milestone Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Package] Block library /packages/block-library [Type] Code Quality Issues or PRs that relate to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants