Skip to content

Charts: Support all CSS color formats in theme colors#46349

Merged
adamwoodnz merged 13 commits intotrunkfrom
copilot/support-hsl-rgb-rgba-colors
Mar 29, 2026
Merged

Charts: Support all CSS color formats in theme colors#46349
adamwoodnz merged 13 commits intotrunkfrom
copilot/support-hsl-rgb-rgba-colors

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Dec 18, 2025

Fixes https://linear.app/a8c/issue/CHARTS-138/support-hsl-rgb-and-rgba-theme-colors

Proposed changes:

  • Add support for HSL, HSLA, RGB, RGBA, and named CSS color formats in theme colors (previously only hex colors were supported)
  • Update normalizeColorToHex to handle hsla(), rgba(), and named CSS colors (e.g. steelblue) via d3-color fallback
  • Refactor color cache building in GlobalChartsProvider to use normalizeColorToHex for all color processing, removing an unreachable guard
  • Deprecate parseRgbString — redundant now that normalizeColorToHex covers all formats
  • Add mixed-color-formats Storybook theme for visual verification of color normalization
  • Add comprehensive test coverage for all color format support

Other information:

  • Have you written new tests for your changes, if applicable?
  • Have you checked the E2E test CI results, and verified that your changes do not break them?
  • Have you tested your changes on WordPress.com, if applicable (if so, you'll see a generated comment below with a script to run)?

Jetpack product discussion

https://linear.app/a8c/review/charts-add-global-theme-support-for-generating-colors-from-a-single-842566402164#comment-ce4ba572

Does this pull request change what data or activity we track or use?

No

Testing instructions:

Setup

  1. Navigate to the charts package: cd projects/js-packages/charts
  2. Install dependencies: pnpm install

Verify the fix

  1. Run tests: pnpm test
    • All tests should pass
    • Look for new HSLA, named color tests in color-utils.test.ts and RGB/HSL/RGBA tests in chart-context.test.tsx
  2. Run the build: pnpm run build
  3. Run type checking: pnpm run typecheck

Verify in Storybook

  1. Start Storybook and select the mixed-color-formats theme from the theme selector
  2. Verify charts render correctly with colors defined in hex, RGB, RGBA, HSL, HSLA, and named color formats (e.g. steelblue)

Technical details

Before this change: CSS variables resolving to rgb(), rgba(), hsl(), hsla(), or named colors were silently skipped during color cache building because the code only checked for colors starting with #.

After this change: All color formats are normalized using normalizeColorToHex, which:

  • Resolves CSS variables using resolveCssVariable
  • Converts RGB, RGBA, HSL, and HSLA to hex format using d3-color
  • Handles 3-digit hex expansion (e.g., #bad#bbaadd)
  • Supports named CSS colors (e.g., steelblue#4682b4) via d3-color fallback
  • Falls back to returning the original value for truly unrecognized formats

Note: Alpha channel information in RGBA/HSLA colors is stripped during hex conversion (d3-color formatHex() behavior). Fully transparent colors (alpha=0) convert to #000000.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Dec 18, 2025

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@adamwoodnz
Copy link
Copy Markdown
Contributor

@copilot try to commit again. I have updated your firewall allowlist

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Dec 18, 2025

@copilot try to commit again. I have updated your firewall allowlist

The commit has been successfully pushed! The branch is now up to date with all changes for CHARTS-138, including:

  • Support for HSL, RGB, and RGBA color formats
  • Updated tests (all 667 passing)
  • Changelog entry

Commit: 7cd8804

@adamwoodnz
Copy link
Copy Markdown
Contributor

@copilot the description needs to follow .github/PULL_REQUEST_TEMPLATE.md

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Dec 18, 2025

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the copilot/support-hsl-rgb-rgba-colors branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack copilot/support-hsl-rgb-rgba-colors

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Dec 18, 2025

@copilot the description needs to follow .github/PULL_REQUEST_TEMPLATE.md

Updated the PR description to follow the template format with proper sections including Fixes, Proposed changes, Testing instructions, and other required fields.

Copilot AI changed the title [WIP] Add support for hsl, rgb, and rgba theme colors Support HSL, RGB, and RGBA theme colors (CHARTS-138) Dec 18, 2025
@adamwoodnz adamwoodnz added Enhancement Changes to an existing feature — removing, adding, or changing parts of it and removed [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. labels Dec 18, 2025
@jp-launch-control
Copy link
Copy Markdown

jp-launch-control bot commented Dec 18, 2025

Code Coverage Summary

Coverage changed in 2 files.

File Coverage Δ% Δ Uncovered
projects/js-packages/charts/src/providers/chart-context/global-charts-provider.tsx 81/81 (100.00%) 0.00% 0 💚
projects/js-packages/charts/src/utils/color-utils.ts 77/78 (98.72%) 1.32% -1 💚

Full summary · PHP report · JS report

@adamwoodnz adamwoodnz changed the title Support HSL, RGB, and RGBA theme colors (CHARTS-138) Charts: Support HSL, RGB, and RGBA theme colors (CHARTS-138) Dec 18, 2025
@adamwoodnz adamwoodnz requested a review from Copilot December 18, 2025 01:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for HSL, RGB, and RGBA color formats in theme colors, where previously only hex colors were supported. This fix resolves an issue where CSS variables resolving to non-hex color formats were silently skipped during color cache building.

Key Changes:

  • Extended normalizeColorToHex to handle rgba() colors in addition to existing rgb() and hsl() support
  • Refactored color cache building in GlobalChartsProvider to use normalizeColorToHex for all color processing, ensuring consistent handling across all color formats
  • Added comprehensive test coverage for new RGBA format support and CSS variables resolving to RGB/HSL/RGBA values

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
projects/js-packages/charts/src/utils/color-utils.ts Added rgba() to the list of supported color formats in normalizeColorToHex and updated documentation in parseRgbString to clarify it only handles RGB (not RGBA)
projects/js-packages/charts/src/utils/test/color-utils.test.ts Added comprehensive tests for RGBA color conversion including edge cases with alpha channel and fully transparent colors
projects/js-packages/charts/src/providers/chart-context/global-charts-provider.tsx Refactored color cache building to use normalizeColorToHex for all color processing, replacing manual CSS variable resolution with centralized normalization
projects/js-packages/charts/src/providers/chart-context/test/chart-context.test.tsx Added integration tests for CSS variables resolving to RGB, HSL, and RGBA formats, and updated existing test expectations to reflect 3-digit hex expansion behavior
projects/js-packages/charts/changelog/charts-138-support-hsl-rgb-rgba-colors Added changelog entry documenting the new color format support

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@adamwoodnz adamwoodnz force-pushed the copilot/support-hsl-rgb-rgba-colors branch from 7cd8804 to 4a8c502 Compare December 19, 2025 02:04
@adamwoodnz adamwoodnz force-pushed the copilot/support-hsl-rgb-rgba-colors branch from 4a8c502 to 0360588 Compare January 1, 2026 23:54
@claude
Copy link
Copy Markdown

claude bot commented Mar 26, 2026

Claude finished @adamwoodnz's task in 48s —— View job


Code Review

  • Gather context
  • Read changed files
  • Analyze code and write review

The two issues flagged in the previous review have both been addressed in subsequent commits. The PR is now in good shape.

Previous issues — resolved

hsla() not handled — Fixed in be783c28. color-utils.ts:187 now includes trimmed.startsWith( 'hsla(' ) in the condition, and tests covering hsla() conversion have been added (color-utils.test.ts:719-731).

Dead code guard in global-charts-provider.tsx — Removed. The if ( !normalizedColor ) unreachable branch is gone; the code now correctly uses if ( normalizedColor.startsWith( '#' ) ) as the single gate (line 99), which is both correct and covered.

Remaining minor note

The rgba(_, _, _, 0)#000000 behavior (zero-alpha fully transparent color collapses to black) is documented in the test at color-utils.test.ts:753-756 and in the PR description. It's a d3-color limitation rather than a bug in this PR. A theme author using a fully-transparent RGBA as a "skip this slot" signal would get unexpected behavior, but this edge case is unlikely in practice and is now at least documented.

Overall

The implementation is clean, the centralization in normalizeColorToHex is correct, and the test coverage is thorough. Good to go from a code standpoint.

@adamwoodnz adamwoodnz marked this pull request as ready for review March 26, 2026 22:47
@adamwoodnz adamwoodnz requested review from a team and Copilot March 26, 2026 22:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

projects/js-packages/charts/src/utils/color-utils.ts:200

  • normalizeColorToHex() currently only calls d3-color for hsl()/hsla()/rgb()/rgba() strings. Named CSS colors (e.g. "steelblue") and other valid CSS color syntaxes will fall through to the "Unknown format" path and be returned as-is, which means GlobalChartsProvider will skip them when building the palette (it only keeps values starting with "#"). If the intent is to support named colors (as implied by the Storybook theme/PR description), add a fallback that attempts d3Color(trimmed) for non-hex, non-CSS-var inputs and returns formatHex() when parsing succeeds, plus a unit test for at least one named color.
	// Handle HSL, HSLA, RGB, and RGBA strings using d3-color
	if (
		trimmed.startsWith( 'hsl(' ) ||
		trimmed.startsWith( 'hsla(' ) ||
		trimmed.startsWith( 'rgb(' ) ||
		trimmed.startsWith( 'rgba(' )
	) {
		const parsed = d3Color( trimmed );
		if ( parsed ) {
			return parsed.formatHex();
		}
		return color;
	}

	// Unknown format, return as-is
	return color;
};

adamwoodnz and others added 3 commits March 27, 2026 12:11
Alpha blending with a background color can't be done reliably
since we don't know the actual rendered background. Keep the
simpler alpha-stripping behavior from d3-color's formatHex().

Use a pre-blended RGB value for the leaderboard secondary color
in the mixed-color-formats theme so it's visually distinct from
the primary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Named colors like "steelblue" were falling through to the
"unknown format" path and returned as-is. Since the provider
only keeps values starting with "#", these were silently
dropped from the palette. Add a d3-color fallback for any
unrecognized format before returning as-is.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adamwoodnz adamwoodnz changed the title Charts: Support HSL, HSLA, RGB, and RGBA theme colors Charts: Support all CSS color formats in theme colors Mar 26, 2026
@adamwoodnz adamwoodnz requested a review from Copilot March 26, 2026 23:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

If resolveCss returns the original input unchanged (e.g. due to
case mismatch between "VAR(--x)" and "var(--x)"), normalizeColorToHex
would recurse infinitely. Skip recursion when resolved === color.

Also update the docblock to reflect all supported formats.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adamwoodnz
Copy link
Copy Markdown
Contributor

@claude final review please

@claude
Copy link
Copy Markdown

claude bot commented Mar 26, 2026

Claude finished @adamwoodnz's task in 54s —— View job


Final Code Review

  • Gather context
  • Read changed files
  • Analyze and write review

All issues from the two previous rounds of review have been addressed. The PR is ready to merge.

Previous issues — all resolved

Issue Status
hsla() not handled ✅ Fixed — trimmed.startsWith('hsla(') added at color-utils.ts:187
Dead !normalizedColor guard ✅ Removed — global-charts-provider.tsx:99 now uses a clean startsWith('#') gate
Infinite recursion on unresolvable CSS var ✅ Fixed — resolved !== color guard at color-utils.ts:175
Stale docblock ✅ Updated — lists hex, HSL, HSLA, RGB, RGBA, named colors, and CSS variables
HSLA zero-alpha test description mismatch ✅ Fixed — test at color-utils.test.ts:728 now reads "converts fully transparent hsla to #000000"
Named color steelblue in Storybook theme ✅ Supported — d3-color fallback at color-utils.ts:199-202 handles it; test at color-utils.test.ts:761 verifies
Changelog missing trailing period ✅ Fixed

One minor note

The changelog text (charts-138-support-hsl-rgb-rgba-colors:4) says "Support HSL, RGB, and RGBA theme colors" but the implementation also covers HSLA and named CSS colors. Not a blocker — the existing wording is accurate enough for a user-facing changelog entry — but it slightly undersells the change if anyone's searching for HSLA or named color support later.

Overall

The implementation is clean and correct. normalizeColorToHex is now a genuinely comprehensive normalization function with clear fallback behavior, proper recursion guards, and thorough test coverage across all supported formats. Good to merge.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adamwoodnz
Copy link
Copy Markdown
Contributor

One minor note

The changelog text (charts-138-support-hsl-rgb-rgba-colors:4) says "Support HSL, RGB, and RGBA theme colors" but the implementation also covers HSLA and named CSS colors. Not a blocker — the existing wording is accurate enough for a user-facing changelog entry — but it slightly undersells the change if anyone's searching for HSLA or named color support later.

Changelog updated in a66dd11

@adamwoodnz adamwoodnz added [Status] Needs Review This PR is ready for review. and removed [Status] In Progress labels Mar 26, 2026
Copy link
Copy Markdown
Contributor

@dognose24 dognose24 left a comment

Choose a reason for hiding this comment

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

Do we also need to add tests for the new logic resolved !== color?

it( 'returns original when CSS variable resolves to itself', () => {
      const mockResolve = jest.fn().mockImplementation( v => v );
      expect( normalizeColorToHex( '--loop', null, mockResolve ) ).toBe( '--loop' );
  } );

} );
} );

describe( 'Named CSS colors', () => {
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.

👍🏼

adamwoodnz and others added 3 commits March 30, 2026 11:56
The existing `resolved !== color` check only prevented direct
self-references (--a resolving to --a). Indirect cycles like
--a → var(--b) → --a would still cause a stack overflow.

Add a depth counter to cap recursion at 10 levels, which is
more than sufficient for real-world CSS variable chains.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers the direct self-reference case where resolveCss returns the
same value it was given, verifying the `resolved !== color` guard.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cover whitespace trimming, case-insensitive color function parsing
(HSL, RGB, RGBA, VAR), and multi-hop CSS variable resolution chains.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adamwoodnz
Copy link
Copy Markdown
Contributor

Do we also need to add tests for the new logic resolved !== color?

Thanks, covered these cases and a bunch of other edge cases with tests in 3 new commits.

@adamwoodnz adamwoodnz merged commit e24f5f5 into trunk Mar 29, 2026
88 checks passed
@adamwoodnz adamwoodnz deleted the copilot/support-hsl-rgb-rgba-colors branch March 29, 2026 23:58
@github-actions github-actions bot added [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. and removed [Status] Needs Review This PR is ready for review. labels Mar 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Changes to an existing feature — removing, adding, or changing parts of it [JS Package] Charts RNA [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants