Skip to content

ColorPalette: Fix duplicate-key warnings and incorrect selection with identical color values#78004

Merged
ciampo merged 14 commits into
WordPress:trunkfrom
USERSATOSHI:try/fix-duplicate-colors-in-pallete
May 11, 2026
Merged

ColorPalette: Fix duplicate-key warnings and incorrect selection with identical color values#78004
ciampo merged 14 commits into
WordPress:trunkfrom
USERSATOSHI:try/fix-duplicate-colors-in-pallete

Conversation

@USERSATOSHI
Copy link
Copy Markdown
Contributor

@USERSATOSHI USERSATOSHI commented May 6, 2026

What?

Closes #9357

Fix React duplicate-key warning and incorrect swatch selection when two palette entries share the same color value.

Why?

more information in the issue but in nutshell:

Themes can legitimately have two palette slots with the same color (e.g. "Header Background" and "Body Background" both white, so users can later change them independently). Gutenberg used the CSS color string as both the React key and the selection identifier, causing:

  • React warning: Encountered two children with the same key, rgb(29, 16, 22)
  • Both swatches highlighted when either is selected

How?

  • ColorPalette now uses slug as the React key when available, and accepts a selectedSlug prop for accurate swatch highlighting
  • onChange passes (color, index, slug) so callers can round-trip the slug
  • Block editor color panel threads the slug from the stored var:preset|color|{slug} value down to ColorPalette, and passes it back through encodeColorValue on change, bypassing the first-match color search

Testing Instructions

  1. Register two palette entries with the same color value (different slugs)
  2. Open a block's color panel in the sidebar
  3. Confirm no console key warning
  4. Confirm clicking each swatch ticks only that swatch
  5. Confirm the correct slug is saved in the block markup after saving

Use of AI Tools

Developed with GitHub Copilot (Claude Sonnet 4.6). All code reviewed and tested manually.

@github-actions github-actions Bot added [Package] Components /packages/components [Package] Block editor /packages/block-editor labels May 6, 2026
@USERSATOSHI USERSATOSHI marked this pull request as ready for review May 6, 2026 12:37
@USERSATOSHI USERSATOSHI requested review from a team, ajitbohra and ellatrix as code owners May 6, 2026 12:37
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Components, [Package] Block editor.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

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.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @DesignerThan95, @metasaman, @timelsass.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

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

Unlinked contributors: DesignerThan95, metasaman, timelsass.

Co-authored-by: USERSATOSHI <tusharbharti@git.wordpress.org>
Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: designsimply <designsimply@git.wordpress.org>
Co-authored-by: JiveDig <jivedig@git.wordpress.org>
Co-authored-by: timnicholson <timnicholson@git.wordpress.org>
Co-authored-by: nathanrodrigues2111 <nathanrbsf@git.wordpress.org>
Co-authored-by: acketon <acketon@git.wordpress.org>
Co-authored-by: SirLouen <sirlouen@git.wordpress.org>
Co-authored-by: ritoban23 <devrito@git.wordpress.org>
Co-authored-by: catthetech <catthetech@git.wordpress.org>

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

Copy link
Copy Markdown
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Thank you for looking into this!

My preference would be to keep this PR focused on the @wordpress/components code changes, and then follow-up with changes to the @wordpress/block-editor package in a separate PR

Comment thread packages/components/CHANGELOG.md Outdated
Comment thread packages/components/src/color-palette/index.native.js
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 addresses a long-standing issue where duplicate color values in a theme palette cause React duplicate-key warnings and incorrect selection/highlighting behavior in Gutenberg’s color UI. It does so by threading palette slug through ColorPalette selection and through the block editor’s color panel so the chosen palette entry can be uniquely identified even when multiple entries share the same color value.

Changes:

  • Extend ColorPalette to support slug per color, prefer slug-based selection via a new selectedSlug prop, and pass slug as a third argument to onChange.
  • Update block editor global styles color panel + color/gradient control plumbing to extract and round-trip the selected preset slug (storing var:preset|color|{slug} directly).
  • Add/adjust component tests for duplicate palette colors and update changelog.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/components/src/color-palette/types.ts Adds optional slug to color objects; extends onChange signature and introduces selectedSlug prop typing.
packages/components/src/color-palette/index.tsx Uses slug for React keys when available, supports slug-based selection, and passes slug through onChange.
packages/components/src/color-palette/index.native.js Adjusts React Native palette item keys to avoid collisions when duplicate colors exist.
packages/components/src/color-palette/test/index.tsx Updates existing expectations for the new onChange signature; adds tests for duplicate-color palettes and slug selection.
packages/components/CHANGELOG.md Adds an Unreleased changelog entry for the ColorPalette duplicate-color fix.
packages/block-editor/src/components/global-styles/color-panel.js Extracts preset slugs from stored values and encodes selected colors using the slug to avoid first-match-by-color issues.
packages/block-editor/src/components/colors-gradients/control.js Threads colorSlug down to ColorPalette as selectedSlug and passes slug back up via onColorChange.

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

Comment thread packages/components/src/color-palette/index.tsx Outdated
Comment thread packages/components/src/color-palette/test/index.tsx Outdated
Comment thread packages/components/CHANGELOG.md Outdated
@USERSATOSHI
Copy link
Copy Markdown
Contributor Author

Thank you for looking into this!

My preference would be to keep this PR focused on the @wordpress/components code changes, and then follow-up with changes to the @wordpress/block-editor package in a separate PR

I see, Then I will split this PR into 2, this one will be related to components and I will follow up with block editor changes. 👍🏻

@github-actions github-actions Bot removed the [Package] Block editor /packages/block-editor label May 7, 2026
@USERSATOSHI USERSATOSHI changed the title Fix duplicate color palette selection by tracking swatches with slug ColorPalette: Fix duplicate-key warnings and incorrect selection with identical color values May 7, 2026
Copy link
Copy Markdown
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

I feel like we could also add a Storybook example for selectedSlug and duplicate colors.

Something like this (which is also currently buggy, related to the first comment below)
diff --git i/packages/components/src/color-palette/stories/index.story.tsx w/packages/components/src/color-palette/stories/index.story.tsx
index 30671aba62f1..8630faf0da63 100644
--- i/packages/components/src/color-palette/stories/index.story.tsx
+++ w/packages/components/src/color-palette/stories/index.story.tsx
@@ -39,17 +39,21 @@ type ColorPaletteStory = StoryObj< typeof ColorPalette >;
 const Template = ( {
 	onChange,
 	value,
+	selectedSlug,
 	...args
 }: React.ComponentProps< typeof ColorPalette > ) => {
 	const [ color, setColor ] = useState< string | undefined >( value );
+	const [ slug, setSlug ] = useState< string | undefined >( selectedSlug );
 
 	return (
 		<ColorPalette
 			{ ...args }
 			value={ color }
-			onChange={ ( newColor ) => {
+			selectedSlug={ slug }
+			onChange={ ( newColor, index, newSlug ) => {
 				setColor( newColor );
-				onChange?.( newColor );
+				setSlug( newSlug );
+				onChange?.( newColor, index, newSlug );
 			} }
 		/>
 	);
@@ -102,6 +106,19 @@ export const MultipleOrigins: ColorPaletteStory = {
 	},
 };
 
+export const DuplicateColors: ColorPaletteStory = {
+	render: Template,
+	args: {
+		colors: [
+			{ name: 'Dark Background', slug: 'dark-background', color: '#000' },
+			{ name: 'Dark Text', slug: 'dark-text', color: '#000' },
+			{ name: 'Brand', slug: 'brand', color: '#0073aa' },
+		],
+		value: '#000',
+		selectedSlug: 'dark-text',
+	},
+};
+
 export const CSSVariables: ColorPaletteStory = {
 	render: ( args ) => (
 		<div

Comment thread packages/components/src/color-palette/index.tsx
Comment thread packages/components/src/color-palette/index.tsx Outdated
@USERSATOSHI
Copy link
Copy Markdown
Contributor Author

image image

I have updated the code for both storybook and the cases you mentioned

Copy link
Copy Markdown
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

Thank you for working on this.

We can merge once remaining (minor) feedback is addressed

Comment thread packages/components/src/color-palette/index.tsx Outdated
Comment thread packages/components/src/color-palette/types.ts
Comment thread packages/components/src/color-palette/utils.ts
@ciampo ciampo merged commit dfb650e into WordPress:trunk May 11, 2026
40 checks passed
@github-actions github-actions Bot added this to the Gutenberg 23.2 milestone May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Components /packages/components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Duplicate colors in palette causes issues

3 participants