Commit 2a2528a30bf for woocommerce

commit 2a2528a30bfd7732e5a5ad075ee7801c465ac20b
Author: Albert Juhé Lluveras <contact@albertjuhe.com>
Date:   Tue Jul 14 11:59:47 2026 +0200

    Introduce new upgrade warning to the Product Image Gallery block when used in the same template with the Add to Cart + Options block (#66552)

    * Introduce new upgrade warning to the Product Image Gallery block when used in the same template with the Add to Cart + Options block

    * Add changelog

    * Remove only flag from test

    * Use upgradeToBlockifiedProductGallery instead of replaceBlockWithProductGallery

    * Merge notices

    * Move edit utils file

    * Update e2e test

diff --git a/plugins/woocommerce/changelog/update-product-image-gallery-upgrade-notice-with-add-to-cart-with-options b/plugins/woocommerce/changelog/update-product-image-gallery-upgrade-notice-with-add-to-cart-with-options
new file mode 100644
index 00000000000..f30eaa9067e
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-product-image-gallery-upgrade-notice-with-add-to-cart-with-options
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Introduce new upgrade warning to the Product Image Gallery block when used in the same template with the Add to Cart + Options block
diff --git a/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/edit-utils.tsx b/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/edit-utils.tsx
new file mode 100644
index 00000000000..4189f4a78e0
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/edit-utils.tsx
@@ -0,0 +1,29 @@
+/**
+ * External dependencies
+ */
+import { createBlock } from '@wordpress/blocks';
+import { dispatch, select } from '@wordpress/data';
+import { findBlock } from '@woocommerce/utils';
+
+/**
+ * Internal dependencies
+ */
+import metadata from './block.json';
+
+export const upgradeToBlockifiedProductGallery = ( blockClientId: string ) => {
+	const blocks = select( 'core/block-editor' ).getBlocks();
+	const foundBlock = findBlock( {
+		blocks,
+		findCondition: ( block ) =>
+			block.name === metadata.name && block.clientId === blockClientId,
+	} );
+
+	if ( foundBlock ) {
+		const newBlock = createBlock( 'woocommerce/product-gallery' );
+
+		dispatch( 'core/block-editor' ).replaceBlock( blockClientId, newBlock );
+
+		return true;
+	}
+	return false;
+};
diff --git a/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/edit.tsx b/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/edit.tsx
index 1eb34533803..0a16bebcaba 100644
--- a/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/edit.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/edit.tsx
@@ -3,8 +3,10 @@
  */
 import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
 import { Disabled } from '@wordpress/components';
+import { useSelect } from '@wordpress/data';
 import { PLACEHOLDER_IMG_SRC } from '@woocommerce/settings';
 import { BlockEditProps } from '@wordpress/blocks';
+import { findBlock } from '@woocommerce/utils';

 /**
  * Internal dependencies
@@ -33,11 +35,25 @@ const Placeholder = () => {

 const Edit = ( props: BlockEditProps< Record< string, never > > ) => {
 	const blockProps = useBlockProps();
+	const hasAddToCartWithOptionsBlock = useSelect( ( select ) => {
+		const blocks = select( 'core/block-editor' ).getBlocks();
+
+		return !! findBlock( {
+			blocks,
+			findCondition: ( block ) =>
+				block.name === 'woocommerce/add-to-cart-with-options',
+		} );
+	}, [] );

 	return (
 		<div { ...blockProps }>
 			<InspectorControls>
-				<UpgradeNotice blockClientId={ props.clientId } />
+				<UpgradeNotice
+					blockClientId={ props.clientId }
+					showAddToCartWithOptionsCompatibilityNotice={
+						hasAddToCartWithOptionsBlock
+					}
+				/>
 			</InspectorControls>
 			<Disabled>
 				<Placeholder />
diff --git a/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/upgrade-notice.tsx b/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/upgrade-notice.tsx
index 84ef5da26b2..c4711ceb77b 100644
--- a/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/upgrade-notice.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/atomic/blocks/product-elements/product-image-gallery/upgrade-notice.tsx
@@ -3,48 +3,38 @@
  */
 import { __ } from '@wordpress/i18n';
 import { createInterpolateElement } from '@wordpress/element';
-import { select } from '@wordpress/data';
 import { UpgradeDowngradeNotice } from '@woocommerce/editor-components/upgrade-downgrade-notice';
-import { findBlock } from '@woocommerce/utils';

 /**
  * Internal dependencies
  */
-import metadata from './block.json';
-import { replaceBlockWithProductGallery } from '../../../../blocks/product-gallery/edit-utils';
-
-const upgradeToBlockifiedProductGallery = ( blockClientId: string ) => {
-	const blocks = select( 'core/block-editor' ).getBlocks();
-	const foundBlock = findBlock( {
-		blocks,
-		findCondition: ( block ) =>
-			block.name === metadata.name && block.clientId === blockClientId,
-	} );
-
-	if ( foundBlock ) {
-		return replaceBlockWithProductGallery( foundBlock.clientId );
-	}
-	return false;
-};
+import { upgradeToBlockifiedProductGallery } from './edit-utils';

 export const UpgradeNotice = ( {
 	blockClientId,
+	showAddToCartWithOptionsCompatibilityNotice,
 }: {
 	blockClientId: string;
+	showAddToCartWithOptionsCompatibilityNotice: boolean;
 } ) => {
-	const notice = createInterpolateElement(
-		__(
-			'Upgrade to the <strongText /> for more flexibility.',
-			'woocommerce'
-		),
-		{
-			strongText: (
-				<strong>
-					{ __( `Product Gallery block`, 'woocommerce' ) }
-				</strong>
-			),
-		}
-	);
+	const notice = showAddToCartWithOptionsCompatibilityNotice
+		? __(
+				'The classic Product Image Gallery block is not compatible with the Add to Cart + Options block in this template. Switch to the new Product Gallery block for a better experience.',
+				'woocommerce'
+		  )
+		: createInterpolateElement(
+				__(
+					'Upgrade to the <strongText /> for more flexibility.',
+					'woocommerce'
+				),
+				{
+					strongText: (
+						<strong>
+							{ __( `Product Gallery block`, 'woocommerce' ) }
+						</strong>
+					),
+				}
+		  );

 	const buttonLabel = __( 'Use the Product Gallery block', 'woocommerce' );

@@ -55,6 +45,9 @@ export const UpgradeNotice = ( {
 			onActionClick={ () =>
 				upgradeToBlockifiedProductGallery( blockClientId )
 			}
+			status={
+				showAddToCartWithOptionsCompatibilityNotice ? 'warning' : 'info'
+			}
 		>
 			{ notice }
 		</UpgradeDowngradeNotice>
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/add-to-cart-with-options/components/upgrade-product-image-gallery/index.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/add-to-cart-with-options/components/upgrade-product-image-gallery/index.tsx
index bdbe5b0f144..97daf22e811 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/add-to-cart-with-options/components/upgrade-product-image-gallery/index.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/add-to-cart-with-options/components/upgrade-product-image-gallery/index.tsx
@@ -11,7 +11,7 @@ import { findBlock } from '@woocommerce/utils';
 /**
  * Internal dependencies
  */
-import { replaceBlockWithProductGallery } from '../../../product-gallery/edit-utils';
+import { upgradeToBlockifiedProductGallery } from '../../../../atomic/blocks/product-elements/product-image-gallery/edit-utils';

 export const UpgradeProductImageGallery = () => {
 	const [ productImageGalleryBlock, setProductImageGalleryBlock ] =
@@ -49,11 +49,15 @@ export const UpgradeProductImageGallery = () => {
 			isDismissible={ false }
 			actionLabel={ buttonLabel }
 			onActionClick={ () => {
-				replaceBlockWithProductGallery(
-					productImageGalleryBlock.clientId
-				);
-				setProductImageGalleryBlock( null );
+				if (
+					upgradeToBlockifiedProductGallery(
+						productImageGalleryBlock.clientId
+					)
+				) {
+					setProductImageGalleryBlock( null );
+				}
 			} }
+			status="warning"
 		>
 			{ notice }
 		</UpgradeDowngradeNotice>
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/edit-utils.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/edit-utils.tsx
deleted file mode 100644
index 3a9e21a5a5a..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/edit-utils.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * External dependencies
- */
-import { createBlock } from '@wordpress/blocks';
-import { dispatch } from '@wordpress/data';
-
-export const replaceBlockWithProductGallery = ( blockClientId: string ) => {
-	const newBlock = createBlock( 'woocommerce/product-gallery' );
-
-	dispatch( 'core/block-editor' ).replaceBlock( blockClientId, newBlock );
-
-	return true;
-};
diff --git a/plugins/woocommerce/client/blocks/assets/js/editor-components/upgrade-downgrade-notice/upgrade-downgrade-notice.tsx b/plugins/woocommerce/client/blocks/assets/js/editor-components/upgrade-downgrade-notice/upgrade-downgrade-notice.tsx
index 30607ec8eb2..ca1abec1aff 100644
--- a/plugins/woocommerce/client/blocks/assets/js/editor-components/upgrade-downgrade-notice/upgrade-downgrade-notice.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/editor-components/upgrade-downgrade-notice/upgrade-downgrade-notice.tsx
@@ -15,11 +15,14 @@ export function UpgradeDowngradeNotice( {
 	className,
 	actionLabel,
 	onActionClick,
+	status = 'info',
 	...props
 }: UpgradeDowngradeNoticeProps ) {
 	return (
 		<Notice
 			{ ...props }
+			status={ status }
+			politeness="polite"
 			className={ clsx(
 				'wc-block-editor-components-upgrade-downgrade-notice',
 				className
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/product-image-gallery/product-image-gallery.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/product-image-gallery/product-image-gallery.block_theme.spec.ts
index b0f5035df47..d26fe50470f 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/product-image-gallery/product-image-gallery.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/product-image-gallery/product-image-gallery.block_theme.spec.ts
@@ -4,6 +4,11 @@
 import { devices } from '@playwright/test';
 import { test, expect, BLOCK_THEME_SLUG } from '@woocommerce/e2e-utils';

+/**
+ * Internal dependencies
+ */
+import AddToCartWithOptionsPage from '../add-to-cart-with-options/add-to-cart-with-options.page';
+
 const blockData = {
 	name: 'woocommerce/product-image-gallery',
 	productPage: '/product/hoodie/',
@@ -126,4 +131,46 @@ test.describe( `${ blockData.name } editor`, () => {
 			editor.canvas.getByLabel( 'Block: Product Gallery' )
 		).toBeVisible();
 	} );
+
+	test( 'shows the Add to Cart + Options compatibility notice and can be migrated to the Product Gallery block', async ( {
+		page,
+		editor,
+		admin,
+	} ) => {
+		const pageObject = new AddToCartWithOptionsPage( {
+			page,
+			admin,
+			editor,
+		} );
+		await pageObject.updateSingleProductTemplate();
+
+		const productImageGalleryBlock = await editor.getBlockByName(
+			blockData.name
+		);
+		await editor.selectBlocks( productImageGalleryBlock );
+
+		const sidebarSettings = page.getByRole( 'region', {
+			name: 'Editor settings',
+		} );
+
+		await expect(
+			sidebarSettings.getByText(
+				'The classic Product Image Gallery block is not compatible with the Add to Cart + Options block in this template. Switch to the new Product Gallery block for a better experience.'
+			)
+		).toBeVisible();
+
+		await expect(
+			editor.canvas.getByLabel( 'Block: Product Gallery' )
+		).toBeHidden();
+
+		await sidebarSettings
+			.getByRole( 'button', {
+				name: 'Use the Product Gallery block',
+			} )
+			.click();
+
+		await expect(
+			editor.canvas.getByLabel( 'Block: Product Gallery' )
+		).toBeVisible();
+	} );
 } );