Commit 55000587329 for woocommerce

commit 550005873299e16c859108fe133a7742dd3c7925
Author: Raluca Stan <ralucastn@gmail.com>
Date:   Fri Sep 18 14:57:00 2026 +0200

    Simplify and align the empty cart state in the Cart and Mini-Cart blocks (#68560)

    * Align the empty Cart block with the design

    The sad-face icon was a ::before pseudo-element on the empty-cart heading, so
    merchants could only remove it with custom CSS. Drop the rule and the class
    that carried it, and stop forcing the heading down to body font size now that
    the icon is not there to anchor it. Existing Cart pages keep the class in
    their saved markup; it is inert without the stylesheet rule.

    The default empty state now matches the approved design: the heading reads
    "Your cart is empty", the Browse store link is a core Button block reading
    "Return to shop" in the theme's default button style, and the dotted
    separator before New in store is replaced by a spacer. This applies to the
    editor default template, the install-time pattern, and the page content the
    installer creates, so pattern-backed Cart pages pick up the copy and the
    button at render time.

    The default template also centers its headings through the typography style,
    which is what current WordPress versions read; the old textAlign attribute is
    kept for older versions. Without it a freshly inserted Cart block rendered the
    headings left-aligned.

    Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

    * Update the Cart tests for the new empty state

    The install test now checks the pattern renders the new heading and a core
    button and no longer emits the icon class. The e2e page fixture mirrors the
    new default, and the specs assert the new heading text.

    checkCartContent is shared by the block cart and the shortcode cart. The
    shortcode cart still renders the classic notice, so the helper branches on
    isClassicCart instead of asserting the block heading for both.

    That exposed a latent bug in cart.spec.ts: the "empty cart is displayed" step
    navigated without awaiting, then read page.url() to decide which cart it was
    on, so the flag came from the previous page. The old assertion matched both
    messages through a shared substring, which hid the wrong answer; with the two
    messages now different the step has to await the navigation.

    Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

    * Align the empty Mini-Cart with the design

    The empty message pattern emits a centered heading reading "Your cart is
    empty", the same copy and element as the Cart page.

    The shopping button rendered its own border, weight, padding and a hard-coded
    hover colour, so it never matched the theme's buttons or the Return to shop
    button on the Cart page. It now uses the same markup and classes as a core
    Button block on the front end and in the editor, and the Mini-Cart specific
    rules are gone. Colour and block style attributes still apply. WordPress only
    loads the Button block stylesheet on pages that render a Button block, so the
    shopping button enqueues it itself, as the Product Button block already does.

    Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

    * Update the Mini-Cart tests and fixtures for the new empty state

    Both theme fixtures mirror the pattern's heading markup, and the specs assert
    the new empty message.

    Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

    * Refresh the FSE translations doc example

    The worked example mirrors the Mini-Cart empty message pattern, which is now a
    heading with different copy.

    Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

    * Add changelog entry for the empty cart redesign

    Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

    * Add the Return to shop button to the Cart e2e fixture

    The fixture's empty-cart markup only had the heading, spacer and "New
    in store" heading. The real cart-empty-message pattern also renders a
    Return to shop button; the fixture never included it, so it diverged
    from production markup.

    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

    ---------

    Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

diff --git a/plugins/woocommerce/changelog/wooplug-2240-empty-cart-icon b/plugins/woocommerce/changelog/wooplug-2240-empty-cart-icon
new file mode 100644
index 00000000000..58b26a10cde
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooplug-2240-empty-cart-icon
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Simplify and align the empty cart state in the Cart and Mini-Cart blocks.
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/cart/inner-blocks/empty-cart-block/edit.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/cart/inner-blocks/empty-cart-block/edit.tsx
index d072988a6c2..f43d724c873 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/cart/inner-blocks/empty-cart-block/edit.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/cart/inner-blocks/empty-cart-block/edit.tsx
@@ -1,7 +1,7 @@
 /**
  * External dependencies
  */
-import { __, sprintf } from '@wordpress/i18n';
+import { __ } from '@wordpress/i18n';
 import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
 import { innerBlockAreas } from '@woocommerce/blocks-checkout';
 import type { TemplateArray } from '@wordpress/blocks';
@@ -16,42 +16,51 @@ import {
 	getAllowedBlocks,
 } from '../../../cart-checkout-shared';

-const browseStoreTemplate = SHOP_URL
+const returnToShopTemplate = SHOP_URL
 	? [
-			'core/paragraph',
-			{
-				align: 'center',
-				content: sprintf(
-					/* translators: %s is the link to the store product directory. */
-					__( '<a href="%s">Browse store</a>', 'woocommerce' ),
-					SHOP_URL
-				),
-				dropCap: false,
-			},
+			'core/buttons',
+			{ layout: { type: 'flex', justifyContent: 'center' } },
+			[
+				[
+					'core/button',
+					{
+						text: __( 'Return to shop', 'woocommerce' ),
+						url: SHOP_URL,
+					},
+				],
+			],
 	  ]
 	: null;

+// Recent WordPress versions center headings through the typography support and no longer
+// have a textAlign attribute; older ones only know textAlign. Unknown attributes are dropped
+// on insert, so passing both keeps the heading centered on every supported version.
+const centeredHeading = {
+	textAlign: 'center',
+	style: { typography: { textAlign: 'center' } },
+};
+
 const defaultTemplate = [
 	[
 		'core/heading',
 		{
-			textAlign: 'center',
-			content: __( 'Your cart is currently empty!', 'woocommerce' ),
+			...centeredHeading,
+			content: __( 'Your cart is empty', 'woocommerce' ),
 			level: 2,
-			className: 'with-empty-cart-icon wc-block-cart__empty-cart__title',
+			className: 'wc-block-cart__empty-cart__title',
 		},
 	],
-	browseStoreTemplate,
+	returnToShopTemplate,
 	[
-		'core/separator',
+		'core/spacer',
 		{
-			className: 'is-style-dots',
+			height: '40px',
 		},
 	],
 	[
 		'core/heading',
 		{
-			textAlign: 'center',
+			...centeredHeading,
 			content: __( 'New in store', 'woocommerce' ),
 			level: 2,
 		},
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/cart/inner-blocks/empty-cart-block/style.scss b/plugins/woocommerce/client/blocks/assets/js/blocks/cart/inner-blocks/empty-cart-block/style.scss
index 1c96b67ef01..221d2e5765d 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/cart/inner-blocks/empty-cart-block/style.scss
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/cart/inner-blocks/empty-cart-block/style.scss
@@ -1,21 +1,3 @@
-.wc-block-cart__empty-cart__title,
-.editor-styles-wrapper .wc-block-cart__empty-cart__title {
-	font-size: inherit;
-}
-.wc-block-cart__empty-cart__title.with-empty-cart-icon {
-	&::before {
-		content: "";
-		background-color: currentColor;
-		display: block;
-		margin: 0 auto 2em;
-		mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzOCIgaGVpZ2h0PSIzOCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMTkgMEM4LjUwNCAwIDAgOC41MDQgMCAxOXM4LjUwNCAxOSAxOSAxOSAxOS04LjUwNCAxOS0xOVMyOS40OTYgMCAxOSAwWm02LjEyOSAxMi44NzFhMi40NDkgMi40NDkgMCAwIDEgMi40NTIgMi40NTIgMi40NDkgMi40NDkgMCAwIDEtMi40NTIgMi40NTEgMi40NDkgMi40NDkgMCAwIDEtMi40NTItMi40NTEgMi40NDkgMi40NDkgMCAwIDEgMi40NTItMi40NTJaTTExLjY0NSAzMS4yNThjLTIuMDMgMC0zLjY3Ny0xLjYwOS0zLjY3Ny0zLjYgMC0xLjUzMyAyLjE4My00LjYyOCAzLjE4Ny01Ljk2MWEuNjEuNjEgMCAwIDEgLjk4IDBjMS4wMDQgMS4zMzMgMy4xODggNC40MjggMy4xODggNS45NiAwIDEuOTkyLTEuNjQ4IDMuNjAxLTMuNjc4IDMuNjAxWm0xLjIyNi0xMy40ODRhMi40NDkgMi40NDkgMCAwIDEtMi40NTItMi40NTEgMi40NDkgMi40NDkgMCAwIDEgMi40NTItMi40NTIgMi40NDkgMi40NDkgMCAwIDEgMi40NTIgMi40NTIgMi40NDkgMi40NDkgMCAwIDEtMi40NTIgMi40NTFabTEzLjA0IDExLjgxNEE4Ljk4OSA4Ljk4OSAwIDAgMCAxOSAyNi4zNTVjLTEuNjI0IDAtMS42MjQtMi40NTIgMC0yLjQ1MiAzLjQwMiAwIDYuNjEyIDEuNTAyIDguNzg4IDQuMTIyIDEuMDU3IDEuMjU3LS44NTkgMi43OTYtMS44NzggMS41NjNaIi8+PC9zdmc+);
-		mask-position: center;
-		mask-repeat: no-repeat;
-		mask-size: 5em;
-		width: 5em;
-		height: 5em;
-	}
-}
 .wp-block-woocommerce-empty-cart-block > .aligncenter {
 	margin-left: auto !important;
 	margin-right: auto !important;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/editor.scss b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/editor.scss
index 9759825fe19..2b4d2368af8 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/editor.scss
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/editor.scss
@@ -88,10 +88,6 @@
 			position: relative;
 		}
 	}
-
-	.wc-block-mini-cart__shopping-button a {
-		color: currentColor;
-	}
 }

 /* Site Editor preview */
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-shopping-button-block/edit.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-shopping-button-block/edit.tsx
index 6d40a339c8e..6baab734f7d 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-shopping-button-block/edit.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-shopping-button-block/edit.tsx
@@ -3,15 +3,14 @@
  */
 import {
 	useBlockProps,
+	RichText,
 	__experimentalUseColorProps as useColorProps,
 } from '@wordpress/block-editor';
-import EditableButton from '@woocommerce/editor-components/editable-button';

 /**
  * Internal dependencies
  */
 import { defaultStartShoppingButtonLabel } from './constants';
-import { getVariant } from '../utils';

 export const Edit = ( {
 	attributes,
@@ -28,12 +27,24 @@ export const Edit = ( {
 	const colorProps = useColorProps( attributes );
 	const { startShoppingButtonLabel } = attributes;

+	// Same markup and classes as a core Button block, so the theme's button styles apply in the editor too.
+	const linkClassName = [
+		'wp-block-button__link',
+		'wp-element-button',
+		'wc-block-mini-cart__shopping-button',
+		colorProps.className,
+	]
+		.filter( Boolean )
+		.join( ' ' );
+
 	return (
 		<div { ...blockProps }>
-			<EditableButton
-				className={ `wc-block-mini-cart__shopping-button ${
-					colorProps.className || ''
-				}` }
+			<RichText
+				tagName="a"
+				className={ linkClassName }
+				style={ colorProps.style }
+				multiline={ false }
+				allowedFormats={ [] }
 				value={ startShoppingButtonLabel }
 				placeholder={ defaultStartShoppingButtonLabel }
 				onChange={ ( content ) => {
@@ -41,8 +52,6 @@ export const Edit = ( {
 						startShoppingButtonLabel: content,
 					} );
 				} }
-				variant={ getVariant( blockProps.className, 'contained' ) }
-				style={ colorProps.style }
 			/>
 		</div>
 	);
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/style.scss b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/style.scss
index c61bf6f51ef..66cd430a291 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/style.scss
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/style.scss
@@ -169,23 +169,3 @@ h2.wc-block-mini-cart__title {
 		margin-top: $gap;
 	}
 }
-
-.wc-block-mini-cart__shopping-button {
-	display: flex;
-	justify-content: center;
-
-	a {
-		border: 2px solid;
-		color: currentColor;
-		font-weight: 600;
-		padding: $gap-small $gap-large;
-		text-decoration: none;
-
-		&:hover,
-		&:focus {
-			background-color: $gray-900;
-			border-color: $gray-900;
-			color: $white;
-		}
-	}
-}
diff --git a/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-in-FSE-templates.md b/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-in-FSE-templates.md
index 798641879f8..a29c52d4046 100644
--- a/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-in-FSE-templates.md
+++ b/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-in-FSE-templates.md
@@ -29,11 +29,9 @@ Let's take a look at `templates/parts/mini-cart.html`:

 	<!-- wp:woocommerce/empty-mini-cart-contents-block -->
 	<div class="wp-block-woocommerce-empty-mini-cart-contents-block">
-		<!-- wp:paragraph {"align":"center"} -->
-		<p class="has-text-align-center">
-			<strong>Your shopping cart is empty</strong>
-		</p>
-		<!-- /wp:paragraph -->
+		<!-- wp:heading {"textAlign":"center"} -->
+		<h2 class="wp-block-heading has-text-align-center">Your cart is empty</h2>
+		<!-- /wp:heading -->

 		<!-- wp:woocommerce/mini-cart-shopping-button-block -->
 		<div class="wp-block-woocommerce-mini-cart-shopping-button-block"></div>
@@ -47,24 +45,20 @@ Let's take a look at `templates/parts/mini-cart.html`:
 This FSE-template contains the following part:

 ```html
-<p class="has-text-align-center">
-	<strong>Your shopping cart is empty</strong>
-</p>
+<h2 class="wp-block-heading has-text-align-center">Your cart is empty</h2>
 ```

 Having this text hardcoded in a FSE-template causes two problems:

 1. This string can only be edited, when a user is using an FSE-theme, such as [Twenty Twenty-Two](https://wordpress.org/themes/twentytwentytwo/). If the user is using a non-FSE-theme, such as [Twenty Twenty-One](https://wordpress.org/themes/twentytwentyone/) or older, this FSE-template cannot be edited.
-2. Even if a user is using an FSE-theme, every user who uses a site language other than the default must manually change the string `Your shopping cart is empty`.
+2. Even if a user is using an FSE-theme, every user who uses a site language other than the default must manually change the string `Your cart is empty`.

 To handle translations within FSE-templates, we need to find the following code:

 ```html
-<!-- wp:paragraph {"align":"center"} -->
-<p class="has-text-align-center">
-	<strong>Your shopping cart is empty</strong>
-</p>
-<!-- /wp:paragraph -->
+<!-- wp:heading {"textAlign":"center"} -->
+<h2 class="wp-block-heading has-text-align-center">Your cart is empty</h2>
+<!-- /wp:heading -->
 ```

 We then replace this code with the following code:
@@ -85,7 +79,7 @@ public function register_empty_cart_message_block_pattern() {
         array(
             'title'    => __( 'Empty Mini-Cart Message', 'woocommerce' ),
             'inserter' => false,
-            'content'  => '<!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center"><strong>' . __( 'Your shopping cart is empty', 'woocommerce' ) . '</strong></p><!-- /wp:paragraph -->',
+            'content'  => '<!-- wp:heading {"textAlign":"center"} --><h2 class="wp-block-heading has-text-align-center">' . __( 'Your cart is empty', 'woocommerce' ) . '</h2><!-- /wp:heading -->',
         )
     );
 }
diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php
index 8a4db694b76..b72653019d5 100644
--- a/plugins/woocommerce/includes/class-wc-install.php
+++ b/plugins/woocommerce/includes/class-wc-install.php
@@ -3235,9 +3235,9 @@ EOT;
 <!-- wp:woocommerce/empty-cart-block -->
 <div class="wp-block-woocommerce-empty-cart-block"><!-- wp:pattern {"slug":"woocommerce/cart-empty-message"} /-->

-<!-- wp:separator {"className":"is-style-dots"} -->
-<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>
-<!-- /wp:separator -->
+<!-- wp:spacer {"height":"40px"} -->
+<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>
+<!-- /wp:spacer -->

 <!-- wp:pattern {"slug":"woocommerce/cart-new-in-store-message"} /-->

diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
index a7e0e58a744..ddecff17987 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
@@ -730,7 +730,7 @@ class MiniCart extends AbstractBlock {
 			array(
 				'title'    => __( 'Empty Mini-Cart Message', 'woocommerce' ),
 				'inserter' => false,
-				'content'  => '<!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center"><strong>' . __( 'Your shopping cart is empty', 'woocommerce' ) . '</strong></p><!-- /wp:paragraph -->',
+				'content'  => '<!-- wp:heading {"textAlign":"center"} --><h2 class="wp-block-heading has-text-align-center">' . __( 'Your cart is empty', 'woocommerce' ) . '</h2><!-- /wp:heading -->',
 			)
 		);
 	}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
index 76740b48860..fccdd880620 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
@@ -21,21 +21,21 @@ class MiniCartShoppingButtonBlock extends AbstractInnerBlock {
 	 * @return string Rendered block type output.
 	 */
 	protected function render( $attributes, $content, $block ) {
+		// The button uses the core Button block classes, so load that block's stylesheet even when the page has no Button block.
+		wp_enqueue_style( 'wp-block-button' );
+
 		ob_start();
 		$shop_url                     = wc_get_page_permalink( 'shop' );
 		$default_start_shopping_label = __( 'Return to shop', 'woocommerce' );
 		$start_shopping_label         = $attributes['startShoppingButtonLabel'] ? $attributes['startShoppingButtonLabel'] : $default_start_shopping_label;
-		$wrapper_attributes           = get_block_wrapper_attributes( array( 'class' => 'wc-block-components-button wp-element-button wc-block-mini-cart__shopping-button' ) );
+		// Same markup and classes as a core Button block, so the theme's button styles apply.
+		$wrapper_attributes = get_block_wrapper_attributes( array( 'class' => 'wp-block-button__link wp-element-button wc-block-mini-cart__shopping-button' ) );
 		?>
 		<div class="wp-block-button has-text-align-center">
 			<a
 				href="<?php echo esc_attr( $shop_url ); ?>"
 				<?php echo $wrapper_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
-			>
-				<div class="wc-block-components-button__text">
-					<?php echo esc_html( $start_shopping_label ); ?>
-				</div>
-			</a>
+			><?php echo esc_html( $start_shopping_label ); ?></a>
 		</div>
 		<?php
 		return (string) ob_get_clean();
diff --git a/plugins/woocommerce/src/Blocks/BlockTypesController.php b/plugins/woocommerce/src/Blocks/BlockTypesController.php
index 2dac45e144d..b00c3a52440 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypesController.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypesController.php
@@ -260,7 +260,7 @@ final class BlockTypesController {
 			array(
 				'title'    => '',
 				'inserter' => false,
-				'content'  => '<!-- wp:heading {"textAlign":"center","className":"with-empty-cart-icon wc-block-cart__empty-cart__title"} --><h2 class="wp-block-heading has-text-align-center with-empty-cart-icon wc-block-cart__empty-cart__title">' . esc_html__( 'Your cart is currently empty!', 'woocommerce' ) . '</h2><!-- /wp:heading --><!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center"><a href="' . esc_attr( esc_url( $shop_permalink ) ) . '">' . esc_html__( 'Browse store', 'woocommerce' ) . '</a></p><!-- /wp:paragraph -->',
+				'content'  => '<!-- wp:heading {"textAlign":"center","className":"wc-block-cart__empty-cart__title"} --><h2 class="wp-block-heading has-text-align-center wc-block-cart__empty-cart__title">' . esc_html__( 'Your cart is empty', 'woocommerce' ) . '</h2><!-- /wp:heading --><!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} --><div class="wp-block-buttons"><!-- wp:button --><div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href="' . esc_attr( esc_url( $shop_permalink ) ) . '">' . esc_html__( 'Return to shop', 'woocommerce' ) . '</a></div><!-- /wp:button --></div><!-- /wp:buttons -->',
 			)
 		);
 		register_block_pattern(
diff --git a/plugins/woocommerce/tests/e2e/bin/blocks/pages/cart.html b/plugins/woocommerce/tests/e2e/bin/blocks/pages/cart.html
index 8c1c39b0565..0108c5e5a39 100644
--- a/plugins/woocommerce/tests/e2e/bin/blocks/pages/cart.html
+++ b/plugins/woocommerce/tests/e2e/bin/blocks/pages/cart.html
@@ -92,19 +92,27 @@

 	<!-- wp:woocommerce/empty-cart-block -->
 	<div class="wp-block-woocommerce-empty-cart-block">
-		<!-- wp:heading {"textAlign":"center","className":"with-empty-cart-icon wc-block-cart__empty-cart__title"} -->
+		<!-- wp:heading {"textAlign":"center","className":"wc-block-cart__empty-cart__title"} -->
 		<h2
-			class="wp-block-heading has-text-align-center with-empty-cart-icon wc-block-cart__empty-cart__title"
+			class="wp-block-heading has-text-align-center wc-block-cart__empty-cart__title"
 		>
-			Your cart is currently empty!
+			Your cart is empty
 		</h2>
 		<!-- /wp:heading -->

-		<!-- wp:separator {"className":"is-style-dots"} -->
-		<hr
-			class="wp-block-separator has-alpha-channel-opacity is-style-dots"
-		/>
-		<!-- /wp:separator -->
+		<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} -->
+		<div class="wp-block-buttons">
+			<!-- wp:button -->
+			<div class="wp-block-button">
+				<a class="wp-block-button__link wp-element-button" href="/shop/">Return to shop</a>
+			</div>
+			<!-- /wp:button -->
+		</div>
+		<!-- /wp:buttons -->
+
+		<!-- wp:spacer {"height":"40px"} -->
+		<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>
+		<!-- /wp:spacer -->

 		<!-- wp:heading {"textAlign":"center"} -->
 		<h2 class="wp-block-heading has-text-align-center">New in store</h2>
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/cart/cart-block.shopper.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/cart/cart-block.shopper.block_theme.spec.ts
index 5d56b1d4124..66142eb6e9b 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/cart/cart-block.shopper.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/cart/cart-block.shopper.block_theme.spec.ts
@@ -31,7 +31,7 @@ test.describe( 'Shopper → Cart block', () => {

 		await expect(
 			page.getByRole( 'heading', {
-				name: 'Your cart is currently empty!',
+				name: 'Your cart is empty',
 			} )
 		).toBeVisible();

diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts
index dd6312ec7c1..d8ce3319243 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts
@@ -45,7 +45,7 @@ test.describe( `${ blockData.name } Block`, () => {
 				).toBeVisible();
 			} else {
 				await expect( page.getByRole( 'dialog' ) ).toContainText(
-					'Your cart is currently empty!'
+					'Your cart is empty'
 				);
 			}
 		}
@@ -103,7 +103,7 @@ test.describe( `${ blockData.name } Block`, () => {
 		await miniCartUtils.openMiniCart();

 		await expect( page.getByRole( 'dialog' ) ).toContainText(
-			'Your shopping cart is empty'
+			'Your cart is empty'
 		);
 		await expect(
 			page.getByRole( 'link', { name: 'Return to shop' } )
@@ -119,7 +119,7 @@ test.describe( `${ blockData.name } Block`, () => {
 		await miniCartUtils.openMiniCart();

 		await expect( page.getByRole( 'dialog' ) ).toContainText(
-			'Your shopping cart is empty'
+			'Your cart is empty'
 		);

 		await page.getByRole( 'button', { name: 'Close' } ).click();
@@ -135,7 +135,7 @@ test.describe( `${ blockData.name } Block`, () => {
 		await miniCartUtils.openMiniCart();

 		await expect( page.getByRole( 'dialog' ) ).toContainText(
-			'Your shopping cart is empty'
+			'Your cart is empty'
 		);

 		await page.mouse.click( 0, 0 );
@@ -317,9 +317,7 @@ test.describe( `${ blockData.name } Block`, () => {
 			.getByRole( 'button', { name: 'Remove Polo from cart' } )
 			.click();

-		await expect(
-			page.getByText( 'Your shopping cart is empty' )
-		).toBeVisible();
+		await expect( page.getByText( 'Your cart is empty' ) ).toBeVisible();
 	} );

 	test( 'should allow to proceed to the cart page', async ( {
diff --git a/plugins/woocommerce/tests/e2e/tests/cart/add-to-cart.spec.ts b/plugins/woocommerce/tests/e2e/tests/cart/add-to-cart.spec.ts
index ba519a099f5..884ad1cc1b8 100644
--- a/plugins/woocommerce/tests/e2e/tests/cart/add-to-cart.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/cart/add-to-cart.spec.ts
@@ -126,7 +126,7 @@ test.describe(
 						page.locator(
 							'.wc-block-mini-cart__empty-cart-wrapper'
 						)
-					).toContainText( 'Your shopping cart is empty' );
+					).toContainText( 'Your cart is empty' );
 				} );
 			}
 		);
diff --git a/plugins/woocommerce/tests/e2e/tests/cart/cart.spec.ts b/plugins/woocommerce/tests/e2e/tests/cart/cart.spec.ts
index 0336daac4d8..96690e16d7e 100644
--- a/plugins/woocommerce/tests/e2e/tests/cart/cart.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/cart/cart.spec.ts
@@ -159,7 +159,7 @@ cartPages.forEach( ( { name, slug } ) => {
 		{ tag: [ tags.PAYMENTS, tags.SERVICES, tags.HPOS ] },
 		async ( { page, products, tax } ) => {
 			await test.step( 'empty cart is displayed', async () => {
-				page.goto( slug );
+				await page.goto( slug );
 				await checkCartContent( isClassicCart( page ), page, [], tax );
 			} );

diff --git a/plugins/woocommerce/tests/e2e/tests/checkout/checkout-link.spec.ts b/plugins/woocommerce/tests/e2e/tests/checkout/checkout-link.spec.ts
index ebde075e104..837e7cb2fbc 100644
--- a/plugins/woocommerce/tests/e2e/tests/checkout/checkout-link.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/checkout/checkout-link.spec.ts
@@ -109,7 +109,7 @@ test.describe( 'Checkout Link Endpoint', () => {
 				).toBeVisible();

 				await expect(
-					page.getByText( 'Your cart is currently empty!' )
+					page.getByText( 'Your cart is empty' )
 				).toBeVisible();
 			}
 		);
diff --git a/plugins/woocommerce/tests/e2e/themes/blocks/storefront-child__with-block-template-part/parts/mini-cart.html b/plugins/woocommerce/tests/e2e/themes/blocks/storefront-child__with-block-template-part/parts/mini-cart.html
index 0d2280ddcf6..8465ce90d8a 100644
--- a/plugins/woocommerce/tests/e2e/themes/blocks/storefront-child__with-block-template-part/parts/mini-cart.html
+++ b/plugins/woocommerce/tests/e2e/themes/blocks/storefront-child__with-block-template-part/parts/mini-cart.html
@@ -32,9 +32,9 @@
 	<!-- /wp:woocommerce/filled-mini-cart-contents-block -->

 	<!-- wp:woocommerce/empty-mini-cart-contents-block -->
-	<div class="wp-block-woocommerce-empty-mini-cart-contents-block"><!-- wp:paragraph {"align":"center"} -->
-	<p class="has-text-align-center"><strong>Your shopping cart is empty</strong></p>
-	<!-- /wp:paragraph -->
+	<div class="wp-block-woocommerce-empty-mini-cart-contents-block"><!-- wp:heading {"textAlign":"center"} -->
+	<h2 class="wp-block-heading has-text-align-center">Your cart is empty</h2>
+	<!-- /wp:heading -->

 	<!-- wp:woocommerce/mini-cart-shopping-button-block -->
 	<div class="wp-block-woocommerce-mini-cart-shopping-button-block"></div>
diff --git a/plugins/woocommerce/tests/e2e/themes/blocks/theme-with-woo-templates/block-template-parts/mini-cart.html b/plugins/woocommerce/tests/e2e/themes/blocks/theme-with-woo-templates/block-template-parts/mini-cart.html
index f277edf3896..f737fba716a 100644
--- a/plugins/woocommerce/tests/e2e/themes/blocks/theme-with-woo-templates/block-template-parts/mini-cart.html
+++ b/plugins/woocommerce/tests/e2e/themes/blocks/theme-with-woo-templates/block-template-parts/mini-cart.html
@@ -32,9 +32,9 @@
 	<!-- /wp:woocommerce/filled-mini-cart-contents-block -->

 	<!-- wp:woocommerce/empty-mini-cart-contents-block -->
-	<div class="wp-block-woocommerce-empty-mini-cart-contents-block"><!-- wp:paragraph {"align":"center"} -->
-	<p class="has-text-align-center"><strong>Your shopping cart is empty</strong></p>
-	<!-- /wp:paragraph -->
+	<div class="wp-block-woocommerce-empty-mini-cart-contents-block"><!-- wp:heading {"textAlign":"center"} -->
+	<h2 class="wp-block-heading has-text-align-center">Your cart is empty</h2>
+	<!-- /wp:heading -->

 	<!-- wp:woocommerce/mini-cart-shopping-button-block -->
 	<div class="wp-block-woocommerce-mini-cart-shopping-button-block"></div>
diff --git a/plugins/woocommerce/tests/e2e/utils/blocks/frontend/frontend-utils.page.ts b/plugins/woocommerce/tests/e2e/utils/blocks/frontend/frontend-utils.page.ts
index a3172385dd1..6c551e7ac37 100644
--- a/plugins/woocommerce/tests/e2e/utils/blocks/frontend/frontend-utils.page.ts
+++ b/plugins/woocommerce/tests/e2e/utils/blocks/frontend/frontend-utils.page.ts
@@ -163,9 +163,7 @@ export class FrontendUtils {
 		await this.goToCart();

 		// Check if cart is already empty
-		const emptyCartMessage = this.page.getByText(
-			'Your cart is currently empty!'
-		);
+		const emptyCartMessage = this.page.getByText( 'Your cart is empty' );
 		if ( await emptyCartMessage.isVisible() ) {
 			return; // Cart is already empty
 		}
diff --git a/plugins/woocommerce/tests/e2e/utils/cart.ts b/plugins/woocommerce/tests/e2e/utils/cart.ts
index 6feff27f06a..f08dedb360c 100644
--- a/plugins/woocommerce/tests/e2e/utils/cart.ts
+++ b/plugins/woocommerce/tests/e2e/utils/cart.ts
@@ -95,8 +95,11 @@ export async function checkCartContent(
 	tax: any
 ) {
 	if ( products.length === 0 ) {
+		const emptyCartMessage = isClassicCart
+			? 'Your cart is currently empty.'
+			: 'Your cart is empty';
 		await expect(
-			page.locator( 'main' ).getByText( 'Your cart is currently empty' )
+			page.locator( 'main' ).getByText( emptyCartMessage )
 		).toBeVisible();
 		return;
 	}
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-install-test.php b/plugins/woocommerce/tests/php/includes/class-wc-install-test.php
index aad6a1a9776..810fdbbd929 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-install-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-install-test.php
@@ -745,7 +745,7 @@ class WC_Install_Test extends \WC_Unit_Test_Case {
 			'The "New in store" heading should be stored as a pattern reference so it is translated at render time.'
 		);
 		$this->assertStringNotContainsString(
-			'Your cart is currently empty!',
+			'Your cart is empty',
 			$content,
 			'The empty cart title must not be frozen into the page content in the install-time locale.'
 		);
@@ -757,7 +757,7 @@ class WC_Install_Test extends \WC_Unit_Test_Case {
 	}

 	/**
-	 * @testdox Should render the empty cart title, the Browse store link, and the New in store heading from the referenced patterns.
+	 * @testdox Should render the empty cart title, the Return to shop button, and the New in store heading from the referenced patterns.
 	 */
 	public function test_empty_cart_message_patterns_render_expected_markup(): void {
 		$registry = WP_Block_Patterns_Registry::get_instance();
@@ -775,7 +775,7 @@ class WC_Install_Test extends \WC_Unit_Test_Case {
 		);

 		$this->assertStringContainsString(
-			'Your cart is currently empty!',
+			'Your cart is empty',
 			$rendered,
 			'The cart-empty-message pattern should render the empty cart title.'
 		);
@@ -784,15 +784,25 @@ class WC_Install_Test extends \WC_Unit_Test_Case {
 			$rendered,
 			'The rendered empty cart title should keep the markup the installer previously inlined.'
 		);
+		$this->assertStringNotContainsString(
+			'with-empty-cart-icon',
+			$rendered,
+			'The empty cart heading must not carry the class that used to inject the icon via CSS (WOOPLUG-2240).'
+		);
 		$this->assertStringContainsString(
 			'New in store',
 			$rendered,
 			'The cart-new-in-store-message pattern should render the "New in store" heading.'
 		);
 		$this->assertStringContainsString(
-			'Browse store',
+			'Return to shop',
+			$rendered,
+			'The cart-empty-message pattern should render the Return to shop button that the default Cart page lost when it moved to installer-generated content in 8.3.0.'
+		);
+		$this->assertStringContainsString(
+			'wp-block-button__link',
 			$rendered,
-			'The cart-empty-message pattern should render the Browse store link that the default Cart page lost when it moved to installer-generated content in 8.3.0.'
+			'The Return to shop link should render as a core button, matching the empty Mini-Cart.'
 		);
 	}