Commit 75952b25fc for woocommerce
commit 75952b25fc7ae60a482c59ef4f630d8a8f376692
Author: Karol Manijak <20098064+kmanijak@users.noreply.github.com>
Date: Mon Feb 2 19:18:58 2026 +0200
Improve Product Collection inspector controls by better terms search (#63025)
* Use dedicated taxonomy controls in Product Collection inspector
* Add changelog
diff --git a/plugins/woocommerce/changelog/add-better-inspector-controls-product-collection b/plugins/woocommerce/changelog/add-better-inspector-controls-product-collection
new file mode 100644
index 0000000000..ea3ebaca88
--- /dev/null
+++ b/plugins/woocommerce/changelog/add-better-inspector-controls-product-collection
@@ -0,0 +1,4 @@
+Significance: minor
+Type: enhancement
+
+Product Collection: improve taxonomies filters in inspector controls
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/taxonomy-controls/index.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/taxonomy-controls/index.tsx
index 4ff588f973..7c05a92541 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/taxonomy-controls/index.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/taxonomy-controls/index.tsx
@@ -5,6 +5,10 @@ import { Taxonomy } from '@wordpress/core-data/src/entity-types';
import { useMemo } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
+import ProductCategoryControl from '@woocommerce/editor-components/product-category-control';
+import ProductTagControl from '@woocommerce/editor-components/product-tag-control';
+import ProductBrandControl from '@woocommerce/editor-components/product-brand-control';
+import type { SearchListItem } from '@woocommerce/editor-components/search-list-control/types';
import {
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalToolsPanelItem as ToolsPanelItem,
@@ -81,14 +85,55 @@ function TaxonomyControls( {
const termIds = taxQuery?.[ slug ] || [];
const handleChange = createHandleChange( slug );
- return (
- <TaxonomyItem
- key={ slug }
- taxonomy={ taxonomy }
- termIds={ termIds }
- onChange={ handleChange }
- />
- );
+ // Adapter for SearchListControl-based components that return SearchListItem[]
+ const handleSearchListChange = ( items: SearchListItem[] ) => {
+ const ids = items.map( ( { id } ) => Number( id ) );
+ handleChange( ids );
+ };
+
+ // Use dedicated controls for known taxonomies
+ switch ( slug ) {
+ case 'product_cat':
+ return (
+ <ProductCategoryControl
+ key={ slug }
+ selected={ termIds }
+ onChange={ handleSearchListChange }
+ isCompact={ true }
+ type="token"
+ />
+ );
+ case 'product_tag':
+ return (
+ <ProductTagControl
+ key={ slug }
+ selected={ termIds }
+ onChange={ handleSearchListChange }
+ isCompact={ true }
+ type="token"
+ />
+ );
+ case 'product_brand':
+ return (
+ <ProductBrandControl
+ key={ slug }
+ selected={ termIds }
+ onChange={ handleSearchListChange }
+ isCompact={ true }
+ type="token"
+ />
+ );
+ default:
+ // Fallback to FormTokenField for unknown taxonomies (e.g., attributes)
+ return (
+ <TaxonomyItem
+ key={ slug }
+ taxonomy={ taxonomy }
+ termIds={ termIds }
+ onChange={ handleChange }
+ />
+ );
+ }
};
const createTaxonomyToolsPanelItem = ( taxonomy: Taxonomy ) => {
diff --git a/plugins/woocommerce/client/blocks/tests/e2e/tests/product-collection/inspector-controls.block_theme.spec.ts b/plugins/woocommerce/client/blocks/tests/e2e/tests/product-collection/inspector-controls.block_theme.spec.ts
index 9a83861d21..d048182174 100644
--- a/plugins/woocommerce/client/blocks/tests/e2e/tests/product-collection/inspector-controls.block_theme.spec.ts
+++ b/plugins/woocommerce/client/blocks/tests/e2e/tests/product-collection/inspector-controls.block_theme.spec.ts
@@ -134,16 +134,13 @@ test.describe( 'Product Collection: Inspector Controls', () => {
} ) => {
await pageObject.createNewPostAndInsertBlock();
- const filterName = 'Product categories';
await pageObject.addFilter( 'Show product categories' );
- await pageObject.setFilterComboboxValue( filterName, [ 'Clothing' ] );
- await expect( pageObject.productTitles ).toHaveText( [
- 'Logo Collection',
- ] );
+ await pageObject.checkTaxonomyTerm( 'categories', 'Clothing' );
+ await expect( pageObject.products ).toHaveCount( 8 );
- await pageObject.setFilterComboboxValue( filterName, [
- 'Accessories',
- ] );
+ // Switch to Accessories
+ await pageObject.uncheckTaxonomyTerm( 'categories', 'Clothing' );
+ await pageObject.checkTaxonomyTerm( 'categories', 'Accessories' );
const accessoriesProductNames = [
'Beanie',
'Beanie with Logo',
@@ -174,18 +171,36 @@ test.describe( 'Product Collection: Inspector Controls', () => {
} ) => {
await pageObject.createNewPostAndInsertBlock();
- const filterName = 'Product tags';
await pageObject.addFilter( 'Show product tags' );
- await pageObject.setFilterComboboxValue( filterName, [
- 'Recommended',
+ await pageObject.checkTaxonomyTerm( 'tags', 'Recommended' );
+ await expect( pageObject.productTitles ).toHaveText( [
+ 'Beanie',
+ 'Hoodie',
] );
+
+ await pageObject.publishAndGoToFrontend();
+ await expect( pageObject.productTitles ).toHaveText( [
+ 'Beanie',
+ 'Hoodie',
+ ] );
+ } );
+
+ test( 'Products can be filtered based on brands.', async ( {
+ pageObject,
+ } ) => {
+ await pageObject.createNewPostAndInsertBlock();
+
+ await pageObject.addFilter( 'Show Brands' );
+ await pageObject.checkTaxonomyTerm( 'brands', 'WooCommerce' );
await expect( pageObject.productTitles ).toHaveText( [
+ 'Album',
'Beanie',
'Hoodie',
] );
await pageObject.publishAndGoToFrontend();
await expect( pageObject.productTitles ).toHaveText( [
+ 'Album',
'Beanie',
'Hoodie',
] );
@@ -646,9 +661,7 @@ test.describe( 'Product Collection: Inspector Controls', () => {
await expect( pageObject.products ).toHaveCount( 9 );
await pageObject.addFilter( 'Show product categories' );
- await pageObject.setFilterComboboxValue( 'Product categories', [
- 'Music',
- ] );
+ await pageObject.checkTaxonomyTerm( 'categories', 'Music' );
const productCollectionBlock = await editor.getBlockByName(
'woocommerce/product-collection'
diff --git a/plugins/woocommerce/client/blocks/tests/e2e/tests/product-collection/product-collection.page.ts b/plugins/woocommerce/client/blocks/tests/e2e/tests/product-collection/product-collection.page.ts
index 390a3108e9..c65ea283a3 100644
--- a/plugins/woocommerce/client/blocks/tests/e2e/tests/product-collection/product-collection.page.ts
+++ b/plugins/woocommerce/client/blocks/tests/e2e/tests/product-collection/product-collection.page.ts
@@ -412,6 +412,7 @@ class ProductCollectionPage {
| 'Keyword'
| 'Show product categories'
| 'Show product tags'
+ | 'Show Brands'
| 'Show Product Attributes'
| 'Featured'
| 'Created'
@@ -674,6 +675,38 @@ class ProductCollectionPage {
await this.refreshLocators( 'editor' );
}
+ /**
+ * Check a taxonomy term checkbox (categories, tags, brands).
+ */
+ async checkTaxonomyTerm(
+ taxonomy: 'categories' | 'tags' | 'brands',
+ term: string
+ ) {
+ const sidebarSettings = this.locateSidebarSettings();
+ const taxonomyContainer = sidebarSettings.locator(
+ `.woocommerce-product-${ taxonomy }`
+ );
+ await taxonomyContainer.waitFor();
+ await taxonomyContainer.getByText( term, { exact: true } ).check();
+ await this.refreshLocators( 'editor' );
+ }
+
+ /**
+ * Uncheck a taxonomy term checkbox (categories, tags, brands).
+ */
+ async uncheckTaxonomyTerm(
+ taxonomy: 'categories' | 'tags' | 'brands',
+ term: string
+ ) {
+ const sidebarSettings = this.locateSidebarSettings();
+ const taxonomyContainer = sidebarSettings.locator(
+ `.woocommerce-product-${ taxonomy }`
+ );
+ await taxonomyContainer.waitFor();
+ await taxonomyContainer.getByText( term, { exact: true } ).uncheck();
+ await this.refreshLocators( 'editor' );
+ }
+
async setInheritQueryFromTemplate( inheritQueryFromTemplate: boolean ) {
const sidebarSettings = this.locateSidebarSettings();
const queryTypeLocator = sidebarSettings.locator(