Commit 7c8a860caff for woocommerce

commit 7c8a860caff9c3759230a80884068aebeaa6d080
Author: Tung Du <dinhtungdu@gmail.com>
Date:   Wed May 13 16:39:17 2026 +0700

    Add color swatch to product filter checkbox list (#64685)

    * Add color swatch to product filter checkbox list for visual attributes

    Display circular color swatches next to checkbox labels when the attribute
    type is wc-visual. Supports server-rendered and Interactivity API paths,
    with an empty-state diagonal line for terms without a color value.

    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

    * Add changelog for color swatch in product filter checkbox list

    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

    * Add changefile(s) from automation for the following project(s): woocommerce

    * Add color swatch to product filter checkbox list editor preview

    Extend editor rendering to show color swatches for visual attributes:

    - Register color term meta with show_in_rest for visual attribute taxonomies
    - Pass visual attribute term colors via AssetDataRegistry to the editor
    - Detect visual attributes in attribute-filter edit and add color to items
    - Render color swatch in checkbox-list edit component

    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

    * Remove changelog files — feature is behind feature flag

    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

    * Revert attribute filter files to trunk — color support already merged via #64694

    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

    * Remove outline style from checked color swatches

    The checkbox check mark is sufficient to indicate selected state.

    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

    * fix minor style

    ---------

    Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
    Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>

diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/edit.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/edit.tsx
index b9ce18e7bf8..9d62a022f74 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/edit.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/edit.tsx
@@ -122,6 +122,26 @@ const CheckboxListEdit = ( props: EditProps ): JSX.Element => {
 											/>
 										</span>
 										<span className="wc-block-product-filter-checkbox-list__text-wrapper">
+											{ item.color !== undefined && (
+												<span
+													className={ clsx(
+														'wc-block-product-filter-checkbox-list__color-swatch',
+														{
+															'is-empty':
+																! item.color,
+														}
+													) }
+													style={
+														item.color
+															? {
+																	backgroundColor:
+																		item.color,
+															  }
+															: undefined
+													}
+													aria-hidden="true"
+												/>
+											) }
 											<span className="wc-block-product-filter-checkbox-list__text">
 												{ typeof item.label === 'string'
 													? decodeHtmlEntities(
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/frontend.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/frontend.ts
index 204204e329d..f247eefc4d4 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/frontend.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/frontend.ts
@@ -8,7 +8,7 @@ import { store, getContext } from '@wordpress/interactivity';
  */
 import type { SelectableItem } from '../../../../types/type-defs/selectable-items';

-type ItemWithIndex = SelectableItem & { index?: number };
+type ItemWithIndex = SelectableItem & { index?: number; color?: string };

 type CheckboxListContext = {
 	storeNamespace: string;
@@ -24,6 +24,8 @@ type CheckboxListStore = {
 	state: {
 		itemHidden: boolean;
 		ratingStyle: string;
+		colorSwatchStyle: string;
+		isColorSwatchEmpty: boolean;
 	};
 	actions: {
 		showAll: () => void;
@@ -55,6 +57,17 @@ const { state }: CheckboxListStore = store< CheckboxListStore >(
 				if ( ! item ) return '';
 				return `width: ${ Number( item.value ) * 20 }%`;
 			},
+			get colorSwatchStyle(): string {
+				const { storeNamespace } = getContext< CheckboxListContext >();
+				const item = getParentItem( storeNamespace );
+				if ( ! item?.color ) return '';
+				return `background-color: ${ item.color }`;
+			},
+			get isColorSwatchEmpty(): boolean {
+				const { storeNamespace } = getContext< CheckboxListContext >();
+				const item = getParentItem( storeNamespace );
+				return ! item?.color;
+			},
 		},
 		actions: {
 			showAll() {
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/style.scss b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/style.scss
index 9212da868ad..aebd84a8656 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/style.scss
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/checkbox-list/style.scss
@@ -123,6 +123,26 @@ input[type="checkbox"].wc-block-product-filter-checkbox-list__input:checked {
 	white-space: nowrap;
 }

+.wc-block-product-filter-checkbox-list__color-swatch {
+	border-radius: 50%;
+	border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
+	display: inline-block;
+	flex-shrink: 0;
+	height: 1em;
+	margin-right: 0.25em;
+	width: 1em;
+
+	&.is-empty {
+		background: linear-gradient(
+			to bottom right,
+			transparent calc(50% - 0.5px),
+			color-mix(in srgb, currentColor 20%, transparent) calc(50% - 0.5px),
+			color-mix(in srgb, currentColor 20%, transparent) calc(50% + 0.5px),
+			transparent calc(50% + 0.5px)
+		);
+	}
+}
+
 .wc-block-product-filter-checkbox-list__stars {
 	display: inline-block;
 	height: 1.55em;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/chips/style.scss b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/chips/style.scss
index 2da9a67c986..e08e1623879 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/chips/style.scss
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/chips/style.scss
@@ -117,6 +117,7 @@
 		border-radius: 50%;
 		border: 1px solid transparent;
 		outline: none;
+		color: inherit;

 		&:hover {
 			border-color: color-mix(in srgb, currentColor 40%, transparent);
@@ -143,9 +144,9 @@
 			background: linear-gradient(
 				to top left,
 				transparent calc(50% - 0.5px),
-				color-mix(in srgb, currentColor 40%, transparent)
+				color-mix(in srgb, currentColor 20%, transparent)
 					calc(50% - 0.5px),
-				color-mix(in srgb, currentColor 40%, transparent)
+				color-mix(in srgb, currentColor 20%, transparent)
 					calc(50% + 0.5px),
 				transparent calc(50% + 0.5px)
 			);
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterCheckboxList.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterCheckboxList.php
index f77a66cf8b9..24387b3e96f 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterCheckboxList.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterCheckboxList.php
@@ -82,6 +82,7 @@ final class ProductFilterCheckboxList extends AbstractBlock {
 		$hidden_count   = max( 0, count( $items ) - count( $visible_items ) );
 		$first_item     = reset( $items );
 		$show_counts    = is_array( $first_item ) && array_key_exists( 'count', $first_item );
+		$has_colors     = is_array( $first_item ) && array_key_exists( 'color', $first_item );

 		ob_start();
 		?>
@@ -137,6 +138,15 @@ final class ProductFilterCheckboxList extends AbstractBlock {
 											<?php echo $stars_svg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
 										</span>
 									<?php else : ?>
+										<?php if ( $has_colors ) : ?>
+											<span
+												class="wc-block-product-filter-checkbox-list__color-swatch<?php echo empty( $item['color'] ) ? ' is-empty' : ''; ?>"
+												<?php if ( ! empty( $item['color'] ) ) : ?>
+													style="background-color: <?php echo esc_attr( $item['color'] ); ?>"
+												<?php endif; ?>
+												aria-hidden="true"
+											></span>
+										<?php endif; ?>
 										<span class="wc-block-product-filter-checkbox-list__text">
 											<?php echo esc_html( $item['label'] ); ?>
 										</span>
@@ -185,6 +195,14 @@ final class ProductFilterCheckboxList extends AbstractBlock {
 											<?php echo $stars_svg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
 										</span>
 									<?php else : ?>
+										<?php if ( $has_colors ) : ?>
+											<span
+												class="wc-block-product-filter-checkbox-list__color-swatch"
+												data-wp-class--is-empty="woocommerce/product-filter-checkbox-list::state.isColorSwatchEmpty"
+												data-wp-bind--style="woocommerce/product-filter-checkbox-list::state.colorSwatchStyle"
+												aria-hidden="true"
+											></span>
+										<?php endif; ?>
 										<span
 											class="wc-block-product-filter-checkbox-list__text"
 											data-wp-text="context.item.label"