Commit 5cdf67c9b3e for woocommerce

commit 5cdf67c9b3e316164f83a3a31a674980e2d121eb
Author: Poli Gilad <83961704+poligilad-auto@users.noreply.github.com>
Date:   Thu Jun 25 16:26:24 2026 +0200

    Improve legacy WooCommerce dashboard widgets (#65704)

    * Improve legacy WooCommerce dashboard widgets

    * Add changelog entry for dashboard widget improvements

    * Fix dashboard widget static analysis

    * Always show legacy WooCommerce dashboard widgets

    * Show status widget labels before values

    * Reduce status widget value size

    * Darken status widget labels

    * Refine dashboard widget visual polish

    * Tighten empty reviews widget spacing

    * Fix dashboard widget lint issues

    * Fix dashboard widget PHP indentation

    * Clarify dashboard widget order coverage

    * Register status widget chart dependency

    * Hide reviews widget when reviews are disabled

    * Honor default reviews setting for dashboard widget

    * Align dashboard color variable spacing

    * Simplify dashboard loading assertions

    * Address dashboard widget review feedback

    * Fix dashboard setup array alignment

    * Restore setup widget top spacing

    * Align dashboard color variables

    * Match status widget hover color

    * Clip status widget hover corners

    * Update dashboard widget status and review details

    * Fix dashboard review widget translator comment

diff --git a/plugins/woocommerce/changelog/tweak-dashboard-setup-post-launch-widgets b/plugins/woocommerce/changelog/tweak-dashboard-setup-post-launch-widgets
new file mode 100644
index 00000000000..a0070b25a2b
--- /dev/null
+++ b/plugins/woocommerce/changelog/tweak-dashboard-setup-post-launch-widgets
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Show WooCommerce Status and Recent Reviews dashboard widgets during store setup.
diff --git a/plugins/woocommerce/client/legacy/css/_variables.scss b/plugins/woocommerce/client/legacy/css/_variables.scss
index 5e5dbe73c24..5bd91e4ad0f 100644
--- a/plugins/woocommerce/client/legacy/css/_variables.scss
+++ b/plugins/woocommerce/client/legacy/css/_variables.scss
@@ -25,8 +25,14 @@ $contentbg:         #fff !default;                                     // Conten
 $subtext:           #767676 !default;                                  // small, breadcrumbs etc

 // Mirrors @wordpress/base-styles/colors.scss (WP 7.0 admin gray scale).
-$gray-900:          #1e1e1e !default;                                  // Primary admin text
-$gray-700:          #757575 !default;                                  // Placeholder / secondary admin text
+$gray-900:            #1e1e1e !default;                                // Primary admin text
+$gray-700:            #757575 !default;                                // Placeholder / secondary admin text
+$wp-admin-hover-gray: #f0f0f0 !default;                                // WordPress dashboard hover background.
+$wp-admin-text-gray:  #50575e !default;                                // WordPress dashboard text color.
+$wp-admin-icon-gray:  #646970 !default;                                // WordPress dashboard icon color.
+
+// Mirrors @wordpress/base-styles/colors.scss alert colors.
+$wp-alert-red:      #cc1818 !default;

 // Border radius tokens — mirrors WP Design System naming.
 $radius-s:          2px !default;                                      // Small radius: inputs, buttons, selects.
@@ -59,7 +65,7 @@ $grid-unit-60:      48px !default;                                     // Matche
 	--wc-form-border-radius: 4px;
 	--wc-form-border-width: 1px;
 	// Matches WP 7.0 $alert-red token for destructive actions.
-	--wc-destructive: #cc1818;
+	--wc-destructive: #{$wp-alert-red};
 	// Matches WP 7.0 $radius-l token (used on dashboard widgets).
 	--wc-card-border-radius: 8px;
 }
diff --git a/plugins/woocommerce/client/legacy/css/dashboard-setup.scss b/plugins/woocommerce/client/legacy/css/dashboard-setup.scss
index dba246e1f18..3a1f8b4287f 100644
--- a/plugins/woocommerce/client/legacy/css/dashboard-setup.scss
+++ b/plugins/woocommerce/client/legacy/css/dashboard-setup.scss
@@ -25,15 +25,62 @@
 		color: #757575;
 	}

-	.description div {
+	.description {
+		display: flex;
+		align-items: center;
+		gap: 24px;
 		margin-top: 11px;
-		float: left;
-		width: 70%;
 	}

-	.description img {
-		float: right;
-		width: 30%;
+	&__content {
+		flex: 1;
+		min-width: 0;
+
+		h3 {
+			display: flex;
+			align-items: center;
+			flex-wrap: wrap;
+			gap: var(--grid-unit-10, 8px);
+			margin: var(--grid-unit-20, 16px) 0 var(--grid-unit-10, 8px);
+			font-size: 18px;
+			line-height: 1.3;
+		}
+
+		p {
+			margin: 0 0 16px;
+			color: #50575e;
+		}
+	}
+
+	#dashboard-widgets & &__content h3 {
+		margin: var(--grid-unit-20, 16px) 0 var(--grid-unit-10, 8px);
+	}
+
+	&__meta {
+		display: flex;
+		align-items: center;
+		flex-wrap: wrap;
+		gap: var(--grid-unit-10, 8px);
+	}
+
+	&__in-progress {
+		background-color: var(--Alias-bg-bg-surface-warning, #fff2d7);
+		border-radius: 4px;
+		color: var(--Alias-text-text-warning, #4d3716);
+		display: inline-block;
+		font-size: 12px;
+		font-style: normal;
+		font-weight: 400;
+		line-height: 16px;
+		padding: var(--grid-unit-05, 4px) var(--grid-unit-10, 8px);
+	}
+
+	&__image {
+		flex: 0 0 90px;
+		width: 90px;
+		max-width: 90px;
+		height: auto;
+		margin-right: 24px;
 	}

 	.circle-progress {
@@ -42,11 +89,11 @@

 		circle {
 			stroke: #f0f0f0;
-			stroke-width: 1px;
+			stroke-width: 2px;
 		}

 		.bar {
-			stroke: #949494;
+			stroke: #3858e9;
 		}
 	}
 }
diff --git a/plugins/woocommerce/client/legacy/css/dashboard.scss b/plugins/woocommerce/client/legacy/css/dashboard.scss
index d1c611f0518..9ccc6922128 100644
--- a/plugins/woocommerce/client/legacy/css/dashboard.scss
+++ b/plugins/woocommerce/client/legacy/css/dashboard.scss
@@ -13,6 +13,28 @@
 /**
  * Styling begins
  */
+.wc-dashboard-widget-loading {
+	padding: 16px 10px;
+	text-align: center;
+
+	p {
+		align-items: center;
+		display: flex;
+		flex-direction: column;
+		gap: 8px;
+		margin: 0;
+	}
+
+	.spinner {
+		float: none;
+		margin: 0;
+	}
+
+	&__text {
+		color: $gray-700;
+	}
+}
+
 ul.woocommerce_stats {
 	overflow: hidden;
 	zoom: 1;
@@ -48,10 +70,6 @@ ul.woocommerce_stats {

 #woocommerce_dashboard_status {

-	.wc-status-widget-loading {
-		padding: 0 10px;
-	}
-
 	.inside {
 		padding: 0;
 		margin: 0;
@@ -70,6 +88,7 @@ ul.woocommerce_stats {
 	.wc_status_list {
 		overflow: hidden;
 		margin: 0;
+		border-radius: 0 0 var(--wc-card-border-radius, 8px) var(--wc-card-border-radius, 8px);

 		li {
 			width: 50%;
@@ -82,9 +101,16 @@ ul.woocommerce_stats {

 			a {
 				display: block;
-				padding: 9px 12px;
+				padding: 9px 12px 9px 44px;
 				position: relative;
-				font-size: 12px;
+				font-size: 13px;
+				line-height: 1.5;
+				color: $wp-admin-icon-gray;
+
+				&:hover,
+				&:focus {
+					background-color: $wp-admin-hover-gray;
+				}

 				.wc_sparkline {
 					width: 4em;
@@ -99,23 +125,27 @@ ul.woocommerce_stats {
 				}

 				strong {
-					font-size: 18px;
+					font-size: 16px;
 					line-height: 1.2em;
 					font-weight: normal;
 					display: block;
+					color: $gray-900;
 				}

 				&::before {

-					@include icon();
-					font-size: 2em;
-					position: relative;
-					width: auto;
-					line-height: 1.2em;
-					color: #464646;
-					float: left;
-					margin-right: 12px;
-					margin-bottom: 12px;
+					@include icon_dashicons( "\f14c" );
+					font-size: 20px;
+					position: absolute;
+					top: 50%;
+					left: 12px;
+					transform: translateY(-50%);
+					width: 20px;
+					height: 20px;
+					line-height: 20px;
+					color: $wp-admin-icon-gray;
+					float: none;
+					margin: 0;
 				}
 			}
 		}
@@ -124,11 +154,15 @@ ul.woocommerce_stats {
 			border-top: 0;
 		}

+		li:not(.sales-this-month):not(.best-seller-this-month):not(.processing-orders):not(.on-hold-orders):not(.low-in-stock):not(.out-of-stock) {
+			clear: both;
+			width: 100%;
+		}
+
 		li.sales-this-month {
 			width: 100%;

 			a::before {
-				font-family: "Dashicons";
 				content: "\f185";
 			}
 		}
@@ -137,7 +171,7 @@ ul.woocommerce_stats {
 			width: 100%;

 			a::before {
-				content: "\e006";
+				content: "\f174";
 			}
 		}

@@ -145,16 +179,14 @@ ul.woocommerce_stats {
 			border-right: 1px solid #ececec;

 			a::before {
-				content: "\e011";
-				color: $green;
+				content: "\f469";
 			}
 		}

 		li.on-hold-orders {

 			a::before {
-				content: "\e033";
-				color: #999;
+				content: "\f523";
 			}
 		}

@@ -162,16 +194,14 @@ ul.woocommerce_stats {
 			border-right: 1px solid #ececec;

 			a::before {
-				content: "\e016";
-				color: $orange;
+				content: "\f14c";
 			}
 		}

 		li.out-of-stock {

 			a::before {
-				content: "\e013";
-				color: $red;
+				content: "\f158";
 			}
 		}
 	}
@@ -179,30 +209,58 @@ ul.woocommerce_stats {

 #woocommerce_dashboard_recent_reviews {

+	#wc-recent-reviews-widget-content > p {
+		margin-bottom: 0;
+	}
+
+	ul {
+		margin: 0;
+	}
+
 	li {
-		line-height: 1.5em;
+		display: grid;
+		grid-template-columns: 32px minmax(0, 1fr) max-content;
+		column-gap: 10px;
+		align-items: start;
+		font-size: 13px;
+		line-height: 1.4;
 		margin-bottom: 12px;
+
+		&:last-child {
+			margin-bottom: 0;
+		}
 	}

 	h4.meta {
-		line-height: 1.4;
-		margin: -0.2em 0 0 0;
+		grid-column: 2;
+		grid-row: 1;
+		font-size: 13px;
+		line-height: 1.5;
+		margin: 0;
 		font-weight: normal;
-		color: #999;
+		color: $wp-admin-icon-gray;
 	}

 	blockquote {
+		grid-column: 2 / -1;
+		grid-row: 2;
+		line-height: 1.4;
 		padding: 0;
 		margin: 0;
 	}

 	.avatar {
-		float: left;
-		margin: 0 10px 5px 0;
+		float: none;
+		grid-column: 1;
+		grid-row: 1 / span 2;
+		margin: 0;
 	}

 	.star-rating {
-		float: right;
+		float: none;
+		grid-column: 3;
+		grid-row: 1;
+		justify-self: end;
 		overflow: hidden;
 		position: relative;
 		height: 1.5em;
@@ -213,7 +271,7 @@ ul.woocommerce_stats {

 		&::before {
 			content: "\e021\e021\e021\e021\e021";
-			color: darken(#ccc, 10%);
+			color: $wp-admin-icon-gray;
 			float: left;
 			top: 0;
 			left: 0;
@@ -238,7 +296,7 @@ ul.woocommerce_stats {
 			left: 0;
 			letter-spacing: 0.1em;
 			letter-spacing: 0\9; // IE8 & below hack ;-(
-			color: var(--wc-primary);
+			color: $wp-admin-text-gray;
 		}
 	}
 }
diff --git a/plugins/woocommerce/includes/admin/class-wc-admin-dashboard-setup.php b/plugins/woocommerce/includes/admin/class-wc-admin-dashboard-setup.php
index 482654a1a6a..feeda7901f4 100644
--- a/plugins/woocommerce/includes/admin/class-wc-admin-dashboard-setup.php
+++ b/plugins/woocommerce/includes/admin/class-wc-admin-dashboard-setup.php
@@ -8,6 +8,7 @@

 use Automattic\Jetpack\Constants;
 use Automattic\WooCommerce\Admin\Features\Features;
+use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
 use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
 use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;

@@ -72,10 +73,13 @@ if ( ! class_exists( 'WC_Admin_Dashboard_Setup', false ) ) :
 				return;
 			}

-			$button_link           = $this->get_button_link( $task );
-			$completed_tasks_count = $this->get_completed_tasks_count();
-			$step_number           = $this->get_completed_tasks_count() + 1;
-			$tasks_count           = count( $this->get_tasks() );
+			$button_link            = $this->get_button_link( $task );
+			$task_header            = $this->get_task_header( $task );
+			$task_is_in_progress    = $task->is_in_progress();
+			$task_in_progress_label = $task_is_in_progress ? $task->in_progress_label() : '';
+			$completed_tasks_count  = $this->get_completed_tasks_count();
+			$step_number            = $completed_tasks_count + 1;
+			$tasks_count            = count( $this->get_tasks() );

 			// Given 'r' (circle element's r attr), dashoffset = ((100-$desired_percentage)/100) * PI * (r*2).
 			$progress_percentage = ( $completed_tasks_count / $tasks_count ) * 100;
@@ -85,6 +89,68 @@ if ( ! class_exists( 'WC_Admin_Dashboard_Setup', false ) ) :
 			include __DIR__ . '/views/html-admin-dashboard-setup.php';
 		}

+		/**
+		 * Get dashboard widget header data for a task.
+		 *
+		 * @param Task $task Task.
+		 * @return array
+		 */
+		private function get_task_header( $task ) {
+			$asset_url           = WC()->plugin_url() . '/assets/';
+			$task_json           = $task->get_json();
+			$default_task_header = array(
+				'title'        => $task->get_title(),
+				'content'      => $task_json['content'] ?? '',
+				'button_label' => $task_json['actionLabel'] ?? $task->get_title(),
+				'image_url'    => $asset_url . 'images/dashboard-widget-setup.png',
+				'image_alt'    => __( 'WooCommerce setup illustration', 'woocommerce' ),
+			);
+			$task_images         = array(
+				'store_details'        => array(
+					'image_url' => $asset_url . 'images/task_list/store-details-illustration.png',
+					'image_alt' => __( 'Store location illustration', 'woocommerce' ),
+				),
+				'customize-store'      => array(
+					'image_url' => $asset_url . 'images/task_list/customize-store-illustration.svg',
+					'image_alt' => __( 'Customize your store illustration', 'woocommerce' ),
+				),
+				'tax'                  => array(
+					'image_url' => $asset_url . 'images/task_list/tax-illustration.svg',
+					'image_alt' => __( 'Tax illustration', 'woocommerce' ),
+				),
+				'shipping'             => array(
+					'image_url' => $asset_url . 'images/task_list/shipping-illustration.svg',
+					'image_alt' => __( 'Shipping illustration', 'woocommerce' ),
+				),
+				'marketing'            => array(
+					'image_url' => $asset_url . 'images/task_list/sales-illustration.svg',
+					'image_alt' => __( 'Marketing illustration', 'woocommerce' ),
+				),
+				'payments'             => array(
+					'image_url' => $asset_url . 'images/task_list/payment-illustration.svg',
+					'image_alt' => __( 'Payment illustration', 'woocommerce' ),
+				),
+				'woocommerce-payments' => array(
+					'image_url' => $asset_url . 'images/task_list/payment-illustration.svg',
+					'image_alt' => __( 'Payment illustration', 'woocommerce' ),
+				),
+				'products'             => array(
+					'image_url' => $asset_url . 'images/task_list/sales-section-illustration.svg',
+					'image_alt' => __( 'Products illustration', 'woocommerce' ),
+				),
+				'purchase'             => array(
+					'image_url' => $asset_url . 'images/task_list/purchase-illustration.png',
+					'image_alt' => __( 'Purchase illustration', 'woocommerce' ),
+				),
+				'launch-your-store'    => array(
+					'image_url' => $asset_url . 'images/task_list/launch-your-store-illustration.svg',
+					'image_alt' => __( 'Launch your store illustration', 'woocommerce' ),
+				),
+			);
+
+			return array_merge( $default_task_header, $task_images[ $task->get_id() ] ?? array() );
+		}
+
 		/**
 		 * Get the button link for a given task.
 		 *
@@ -165,7 +231,7 @@ if ( ! class_exists( 'WC_Admin_Dashboard_Setup', false ) ) :
 		/**
 		 * Get the next task.
 		 *
-		 * @return array|null
+		 * @return Task|null
 		 */
 		private function get_next_task() {
 			foreach ( $this->get_tasks() as $task ) {
diff --git a/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php b/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php
index 0d1cfb1cd7a..73ebe5cf967 100644
--- a/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php
+++ b/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php
@@ -42,11 +42,12 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 		 * Init dashboard widgets.
 		 */
 		public function init() {
+			wp_add_dashboard_widget( 'woocommerce_dashboard_status', __( 'WooCommerce Status', 'woocommerce' ), array( $this, 'status_widget' ), null, null, 'normal', 'high' );
+
 			// Reviews Widget.
-			if ( current_user_can( 'publish_shop_orders' ) && post_type_supports( 'product', 'comments' ) ) {
-				wp_add_dashboard_widget( 'woocommerce_dashboard_recent_reviews', __( 'WooCommerce Recent Reviews', 'woocommerce' ), array( $this, 'recent_reviews' ) );
+			if ( 'yes' === get_option( 'woocommerce_enable_reviews', 'yes' ) && current_user_can( 'publish_shop_orders' ) && post_type_supports( 'product', 'comments' ) ) {
+				wp_add_dashboard_widget( 'woocommerce_dashboard_recent_reviews', __( 'WooCommerce Recent Reviews', 'woocommerce' ), array( $this, 'recent_reviews' ), null, null, 'normal', 'high' );
 			}
-			wp_add_dashboard_widget( 'woocommerce_dashboard_status', __( 'WooCommerce Status', 'woocommerce' ), array( $this, 'status_widget' ) );

 			// Network Order Widget.
 			if ( is_multisite() && is_main_site() ) {
@@ -71,9 +72,7 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 				return false;
 			}

-			$has_permission           = current_user_can( 'view_woocommerce_reports' ) || current_user_can( 'manage_woocommerce' ) || current_user_can( 'publish_shop_orders' );
-			$task_completed_or_hidden = 'yes' === get_option( 'woocommerce_task_list_complete' ) || 'yes' === get_option( 'woocommerce_task_list_hidden' );
-			return $task_completed_or_hidden && $has_permission;
+			return current_user_can( 'view_woocommerce_reports' ) || current_user_can( 'manage_woocommerce' ) || current_user_can( 'publish_shop_orders' );
 		}

 		/**
@@ -136,6 +135,10 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 			$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
 			$version = Constants::get_constant( 'WC_VERSION' );

+			if ( ! wp_script_is( 'wc-flot', 'registered' ) ) {
+				wp_register_script( 'wc-flot', WC()->plugin_url() . '/assets/js/jquery-flot/jquery.flot' . $suffix . '.js', array( 'jquery' ), $version, true );
+			}
+
 			wp_enqueue_script( 'wc-status-widget', WC()->plugin_url() . '/assets/js/admin/wc-status-widget' . $suffix . '.js', array( 'jquery', 'wc-flot' ), $version, true );
 			wp_enqueue_script( 'wc-status-widget-async', WC()->plugin_url() . '/assets/js/admin/wc-status-widget-async' . $suffix . '.js', array( 'jquery' ), $version, true );

@@ -150,8 +153,8 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 			);

 			// Display loading placeholder.
-			echo '<div id="wc-status-widget-loading" class="wc-status-widget-loading">';
-			echo '<p>' . esc_html__( 'Loading status data...', 'woocommerce' ) . ' <span class="spinner is-active"></span></p>';
+			echo '<div id="wc-status-widget-loading" class="wc-dashboard-widget-loading wc-status-widget-loading" aria-busy="true">';
+			echo '<p><span class="spinner is-active"></span><span class="wc-dashboard-widget-loading__text">' . esc_html__( 'Loading status data...', 'woocommerce' ) . '</span></p>';
 			echo '</div>';
 			echo '<div id="wc-status-widget-content" style="display:none;"></div>';
 		}
@@ -217,7 +220,7 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 					<?php
 						printf(
 							/* translators: %s: net sales */
-							esc_html__( '%s net sales this month', 'woocommerce' ),
+							esc_html__( 'Net sales this month %s', 'woocommerce' ),
 							'<strong>' . wc_price( $report_data->net_sales ) . '</strong>'
 						); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
 					?>
@@ -236,8 +239,8 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 					<?php echo wp_kses( $sparkline, $sparkline_allowed_html ); ?>
 					<?php
 						printf(
-							/* translators: 1: top seller product title 2: top seller quantity */
-							esc_html__( '%1$s top seller this month (sold %2$d)', 'woocommerce' ),
+							/* translators: 1: top seller product title 2: top seller quantity sold */
+							esc_html( _n( 'Top seller this month %1$s (%2$d sale)', 'Top seller this month %1$s (%2$d sales)', $top_seller->qty, 'woocommerce' ) ),
 							'<strong>' . get_the_title( $top_seller->product_id ) . '</strong>',
 							$top_seller->qty
 						); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
@@ -285,22 +288,26 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 			<li class="processing-orders">
 			<a href="<?php echo esc_url( admin_url( 'edit.php?post_status=wc-processing&post_type=shop_order' ) ); ?>">
 				<?php
-					printf(
-						/* translators: %s: order count */
-						_n( '<strong>%s order</strong> awaiting processing', '<strong>%s orders</strong> awaiting processing', $processing_count, 'woocommerce' ),
-						$processing_count
-					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
+					echo wp_kses_post(
+						sprintf(
+							/* translators: %s: order count */
+							_n( 'Awaiting processing <strong>%s order</strong>', 'Awaiting processing <strong>%s orders</strong>', $processing_count, 'woocommerce' ),
+							$processing_count
+						)
+					);
 				?>
 				</a>
 			</li>
 			<li class="on-hold-orders">
 				<a href="<?php echo esc_url( admin_url( 'edit.php?post_status=wc-on-hold&post_type=shop_order' ) ); ?>">
 				<?php
-					printf(
-						/* translators: %s: order count */
-						_n( '<strong>%s order</strong> on-hold', '<strong>%s orders</strong> on-hold', $on_hold_count, 'woocommerce' ),
-						$on_hold_count
-					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
+					echo wp_kses_post(
+						sprintf(
+							/* translators: %s: order count */
+							_n( 'On-hold <strong>%s order</strong>', 'On-hold <strong>%s orders</strong>', $on_hold_count, 'woocommerce' ),
+							$on_hold_count
+						)
+					);
 				?>
 				</a>
 			</li>
@@ -390,22 +397,26 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 			<li class="low-in-stock">
 				<a href="<?php echo esc_url( $lowstock_url ); ?>">
 				<?php
-					printf(
-						/* translators: %s: order count */
-						_n( '<strong>%s product</strong> low in stock', '<strong>%s products</strong> low in stock', $lowinstock_count, 'woocommerce' ),
-						$lowinstock_count
-					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
+					echo wp_kses_post(
+						sprintf(
+							/* translators: %s: order count */
+							_n( 'Low in stock <strong>%s product</strong>', 'Low in stock <strong>%s products</strong>', $lowinstock_count, 'woocommerce' ),
+							$lowinstock_count
+						)
+					);
 				?>
 				</a>
 			</li>
 			<li class="out-of-stock">
 				<a href="<?php echo esc_url( $outofstock_url ); ?>">
 				<?php
-					printf(
-						/* translators: %s: order count */
-						_n( '<strong>%s product</strong> out of stock', '<strong>%s products</strong> out of stock', $outofstock_count, 'woocommerce' ),
-						$outofstock_count
-					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
+					echo wp_kses_post(
+						sprintf(
+							/* translators: %s: order count */
+							_n( 'Out of stock <strong>%s product</strong>', 'Out of stock <strong>%s products</strong>', $outofstock_count, 'woocommerce' ),
+							$outofstock_count
+						)
+					);
 				?>
 				</a>
 			</li>
@@ -493,8 +504,8 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
 			);

 			// Display loading placeholder.
-			echo '<div id="wc-recent-reviews-widget-loading" class="wc-recent-reviews-widget-loading">';
-			echo '<p>' . esc_html__( 'Loading reviews data...', 'woocommerce' ) . ' <span class="spinner is-active"></span></p>';
+			echo '<div id="wc-recent-reviews-widget-loading" class="wc-dashboard-widget-loading wc-recent-reviews-widget-loading" aria-busy="true">';
+			echo '<p><span class="spinner is-active"></span><span class="wc-dashboard-widget-loading__text">' . esc_html__( 'Loading reviews data...', 'woocommerce' ) . '</span></p>';
 			echo '</div>';
 			echo '<div id="wc-recent-reviews-widget-content" style="display:none;"></div>';
 		}
diff --git a/plugins/woocommerce/includes/admin/views/html-admin-dashboard-setup.php b/plugins/woocommerce/includes/admin/views/html-admin-dashboard-setup.php
index 0fe6a9fe366..3f0ac213ae0 100644
--- a/plugins/woocommerce/includes/admin/views/html-admin-dashboard-setup.php
+++ b/plugins/woocommerce/includes/admin/views/html-admin-dashboard-setup.php
@@ -8,22 +8,41 @@
 if ( ! defined( 'ABSPATH' ) ) {
 	exit;
 }
-?>
-<div class="dashboard-widget-finish-setup" data-current-step="<?php echo esc_html( $step_number - 1 ); ?>" data-total-steps="<?php echo esc_html( $tasks_count ); ?>">
-	<span class='progress-wrapper'>
-		<svg class="circle-progress" width="17" height="17" version="1.1" xmlns="http://www.w3.org/2000/svg">
-		  <circle r="6.5" cx="10" cy="10" fill="transparent" stroke-dasharray="40.859" stroke-dashoffset="0"></circle>
-		  <circle class="bar" r="6.5" cx="190" cy="10" fill="transparent" stroke-dasharray="40.859" stroke-dashoffset="<?php echo esc_attr( $circle_dashoffset ); ?>" transform='rotate(-90 100 100)'></circle>
-		</svg>
-		<span><?php esc_html_e( 'Step', 'woocommerce' ); ?> <?php echo esc_html( $step_number ); ?> <?php esc_html_e( 'of', 'woocommerce' ); ?> <?php echo esc_html( $tasks_count ); ?></span>
-	</span>

+/**
+ * Dashboard setup widget view variables.
+ *
+ * @var array{title:string, content:string, button_label:string, image_url:string, image_alt:string} $task_header Task header data.
+ * @var bool $task_is_in_progress Whether the task is in progress.
+ * @var string $task_in_progress_label Task in-progress label.
+ */
+?>
+<div class="dashboard-widget-finish-setup" data-current-step="<?php echo esc_attr( (string) ( $step_number - 1 ) ); ?>" data-total-steps="<?php echo esc_attr( (string) $tasks_count ); ?>">
 	<div class="description">
-		<div>
-			<?php esc_html_e( 'You\'re almost there! Once you complete store setup you can start receiving orders.', 'woocommerce' ); ?>
-			<div><a href='<?php echo esc_attr( $button_link ); ?>' class='button button-primary'><?php esc_html_e( 'Start selling', 'woocommerce' ); ?></a></div>
+		<div class="dashboard-widget-finish-setup__content">
+			<div class="dashboard-widget-finish-setup__meta">
+				<span class='progress-wrapper'>
+					<svg class="circle-progress" width="17" height="17" version="1.1" xmlns="http://www.w3.org/2000/svg">
+						<circle r="6.5" cx="10" cy="10" fill="transparent" stroke-dasharray="40.859" stroke-dashoffset="0"></circle>
+						<circle class="bar" r="6.5" cx="190" cy="10" fill="transparent" stroke-dasharray="40.859" stroke-dashoffset="<?php echo esc_attr( $circle_dashoffset ); ?>" transform='rotate(-90 100 100)'></circle>
+					</svg>
+					<span><?php esc_html_e( 'Step', 'woocommerce' ); ?> <?php echo esc_html( $step_number ); ?> <?php esc_html_e( 'of', 'woocommerce' ); ?> <?php echo esc_html( $tasks_count ); ?></span>
+				</span>
+			</div>
+			<h3 class="dashboard-widget-finish-setup__title">
+				<?php echo esc_html( $task_header['title'] ); ?>
+				<?php if ( $task_is_in_progress && $task_in_progress_label ) : ?>
+					<span class="dashboard-widget-finish-setup__in-progress"><?php echo esc_html( $task_in_progress_label ); ?></span>
+				<?php endif; ?>
+			</h3>
+			<p><?php echo esc_html( $task_header['content'] ); ?></p>
+			<div><a href='<?php echo esc_url( $button_link ); ?>' class='button button-primary'><?php echo esc_html( $task_header['button_label'] ); ?></a></div>
 		</div>
-		<img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/dashboard-widget-setup.png" />
+		<img
+			class="dashboard-widget-finish-setup__image"
+			src="<?php echo esc_url( $task_header['image_url'] ); ?>"
+			alt="<?php echo esc_attr( $task_header['image_alt'] ); ?>"
+		/>
 	</div>
 	<div class="clear"></div>
 </div>
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 60057b96c5b..4bb5b3f118c 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -1722,18 +1722,6 @@ parameters:
 			count: 1
 			path: includes/admin/class-wc-admin-brands.php

-		-
-			message: '#^Call to method get_id\(\) on an unknown class Task\.$#'
-			identifier: class.notFound
-			count: 1
-			path: includes/admin/class-wc-admin-dashboard-setup.php
-
-		-
-			message: '#^Call to method get_json\(\) on an unknown class Task\.$#'
-			identifier: class.notFound
-			count: 1
-			path: includes/admin/class-wc-admin-dashboard-setup.php
-
 		-
 			message: '#^Cannot call method get_viewable_tasks\(\) on array\.$#'
 			identifier: method.nonObject
@@ -1776,18 +1764,6 @@ parameters:
 			count: 1
 			path: includes/admin/class-wc-admin-dashboard-setup.php

-		-
-			message: '#^Parameter \#1 \$task of method WC_Admin_Dashboard_Setup\:\:get_button_link\(\) expects Task, array given\.$#'
-			identifier: argument.type
-			count: 1
-			path: includes/admin/class-wc-admin-dashboard-setup.php
-
-		-
-			message: '#^Parameter \$task of method WC_Admin_Dashboard_Setup\:\:get_button_link\(\) has invalid type Task\.$#'
-			identifier: class.notFound
-			count: 1
-			path: includes/admin/class-wc-admin-dashboard-setup.php
-
 		-
 			message: '#^Property WC_Admin_Dashboard_Setup\:\:\$completed_tasks_count is never read, only written\.$#'
 			identifier: property.onlyWritten
@@ -7914,12 +7890,6 @@ parameters:
 			count: 1
 			path: includes/admin/settings/views/html-webhooks-edit.php

-		-
-			message: '#^Parameter \#1 \$text of function esc_html expects string, \(float\|int\) given\.$#'
-			identifier: argument.type
-			count: 1
-			path: includes/admin/views/html-admin-dashboard-setup.php
-
 		-
 			message: '#^Variable \$button_link might not be defined\.$#'
 			identifier: variable.undefined
diff --git a/plugins/woocommerce/templates/dashboard-widget-reviews.php b/plugins/woocommerce/templates/dashboard-widget-reviews.php
index 6d52951d843..5a149f052b9 100644
--- a/plugins/woocommerce/templates/dashboard-widget-reviews.php
+++ b/plugins/woocommerce/templates/dashboard-widget-reviews.php
@@ -12,7 +12,7 @@
  *
  * @see     https://woocommerce.com/document/template-structure/
  * @package WooCommerce\Templates
- * @version 10.5.0
+ * @version 11.0.0
  */

 defined( 'ABSPATH' ) || exit;
@@ -24,6 +24,11 @@ defined( 'ABSPATH' ) || exit;
  * @var $comment \WP_Comment
  */

+$product_name          = $product->get_name();
+$product_name_display  = wc_trim_string( $product_name, 40 );
+$review_author         = get_comment_author( $comment->comment_ID );
+$review_author_display = wc_trim_string( $review_author, 24 );
+
 ?>

 <li>
@@ -36,10 +41,22 @@ defined( 'ABSPATH' ) || exit;
 	<?php echo wc_get_rating_html( (int) get_comment_meta( $comment->comment_ID, 'rating', true ) ); ?>

 	<h4 class="meta">
-		<a href="<?php echo esc_url( get_comment_link( $comment->comment_ID ) ); ?>"><?php echo wp_kses_post( $product->get_name() ); ?></a>
+		<a href="<?php echo esc_url( get_comment_link( $comment->comment_ID ) ); ?>" title="<?php echo esc_attr( $product_name ); ?>"><?php echo wp_kses_post( $product_name_display ); ?></a>
 		<?php
-		/* translators: %s: review author */
-		printf( esc_html__( 'reviewed by %s', 'woocommerce' ), esc_html( get_comment_author( $comment->comment_ID ) ) );
+		$reviewed_by = sprintf(
+			// translators: %s: review author.
+			__( 'reviewed by %s', 'woocommerce' ),
+			'<span title="' . esc_attr( $review_author ) . '">' . esc_html( $review_author_display ) . '</span>'
+		);
+
+		echo wp_kses(
+			$reviewed_by,
+			array(
+				'span' => array(
+					'title' => true,
+				),
+			)
+		);
 		?>
 	</h4>

diff --git a/plugins/woocommerce/tests/legacy/unit-tests/admin/class-wc-tests-admin-dashboard.php b/plugins/woocommerce/tests/legacy/unit-tests/admin/class-wc-tests-admin-dashboard.php
index 87863f5643d..fdd5fbe815a 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/admin/class-wc-tests-admin-dashboard.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/admin/class-wc-tests-admin-dashboard.php
@@ -44,6 +44,7 @@ class WC_Tests_Admin_Dashboard extends WC_Unit_Test_Case {
 		wp_set_current_user( $this->user );
 		( new WC_Admin_Dashboard() )->recent_reviews();
 		$this->expectOutputRegex( '/Loading reviews data.../' );
+		$this->expectOutputRegex( '/wc-dashboard-widget-loading/' );
 		$this->expectOutputRegex( '/wc-recent-reviews-widget-loading/' );
 		$this->expectOutputRegex( '/wc-recent-reviews-widget-content/' );
 	}
@@ -69,6 +70,39 @@ class WC_Tests_Admin_Dashboard extends WC_Unit_Test_Case {
 		$product->delete();
 	}

+	/**
+	 * Test: recent reviews widget truncates long product and reviewer names.
+	 */
+	public function test_recent_reviews_widget_content_truncates_long_product_and_reviewer_names() {
+		$product_name = 'Extra long dashboard review stress test product name with multiple descriptive words';
+		$author_name  = 'Alexandria Montgomery-Silverstein With A Very Long Reviewer Name';
+		$product      = WC_Helper_Product::create_simple_product();
+		$product->set_name( $product_name );
+		$product->save();
+
+		$comment_id = WC_Helper_Product::create_product_review( $product->get_id(), 'Review content here' );
+		wp_update_comment(
+			array(
+				'comment_ID'       => $comment_id,
+				'comment_author'   => $author_name,
+				'comment_date'     => current_time( 'mysql' ),
+				'comment_date_gmt' => current_time( 'mysql', true ),
+			)
+		);
+
+		wp_set_current_user( $this->user );
+		ob_start();
+		( new WC_Admin_Dashboard() )->recent_reviews_content();
+		$html = ob_get_clean();
+
+		$this->assertStringContainsString( 'title="' . esc_attr( $product_name ) . '"', $html );
+		$this->assertStringContainsString( '>' . esc_html( wc_trim_string( $product_name, 40 ) ) . '</a>', $html );
+		$this->assertStringContainsString( 'title="' . esc_attr( $author_name ) . '"', $html );
+		$this->assertStringContainsString( '>' . esc_html( wc_trim_string( $author_name, 24 ) ) . '</span>', $html );
+
+		$product->delete();
+	}
+
 	/**
 	 * Test: recent reviews widget content (legacy).
 	 */
@@ -102,7 +136,7 @@ class WC_Tests_Admin_Dashboard extends WC_Unit_Test_Case {
 		wp_set_current_user( $this->user );
 		( new WC_Admin_Dashboard() )->status_widget();
 		$this->expectOutputRegex( '/Loading status data.../' );
-		$this->expectOutputRegex( '/<div id="wc-status-widget-loading" class="wc-status-widget-loading">/' );
+		$this->expectOutputRegex( '/<div id="wc-status-widget-loading" class="wc-dashboard-widget-loading wc-status-widget-loading" aria-busy="true">/' );
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-setup-test.php b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-setup-test.php
index 76244247638..784dfd41713 100644
--- a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-setup-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-setup-test.php
@@ -160,8 +160,8 @@ class WC_Admin_Dashboard_Setup_Test extends WC_Unit_Test_Case {

 		$required_strings = array(
 			'Step \d+ of \d+',
-			'You&#039;re almost there! Once you complete store setup you can start receiving orders.',
-			'Start selling',
+			'dashboard-widget-finish-setup__title',
+			'dashboard-widget-finish-setup__image',
 		);

 		foreach ( $required_strings as $required_string ) {
@@ -169,6 +169,72 @@ class WC_Admin_Dashboard_Setup_Test extends WC_Unit_Test_Case {
 		}
 	}

+	/**
+	 * Tests the widget output when the next task is in progress.
+	 *
+	 * @testdox Widget output includes the in-progress label for the next task.
+	 */
+	public function test_widget_output_includes_in_progress_label() {
+		// phpcs:disable Squiz.Commenting
+		$task_list = new class() {
+			public function is_complete() {
+				return false;
+			}
+			public function is_hidden() {
+				return false;
+			}
+			public function get_viewable_tasks() {
+				return array(
+					new class() extends \Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task {
+						public function get_id() {
+							return 'payments';
+						}
+						public function get_title() {
+							return 'Set up payments';
+						}
+						public function get_content() {
+							return 'Choose payment providers and enable payment methods at checkout.';
+						}
+						public function get_time() {
+							return '5 minutes';
+						}
+						public function get_action_url() {
+							return 'payments';
+						}
+						public function get_action_label() {
+							return 'Configure payments';
+						}
+						public function is_complete() {
+							return false;
+						}
+						public function is_in_progress() {
+							return true;
+						}
+						public function in_progress_label() {
+							return 'Test account';
+						}
+					},
+				);
+			}
+		};
+		// phpcs:enable Squiz.Commenting
+
+		$widget = $this->get_widget();
+		$widget->set_task_list( $task_list );
+
+		ob_start();
+		$widget->render();
+		$html = ob_get_clean();
+
+		$this->assertStringContainsString( 'dashboard-widget-finish-setup__in-progress', $html );
+		$this->assertStringContainsString( 'Set up payments', $html );
+		$this->assertStringContainsString( 'Choose payment providers and enable payment methods at checkout.', $html );
+		$this->assertStringContainsString( 'Configure payments', $html );
+		$this->assertStringContainsString( 'payment-illustration.svg', $html );
+		$this->assertStringContainsString( 'Test account', $html );
+		$this->assertMatchesRegularExpression( '/<h3 class="dashboard-widget-finish-setup__title">.*Test account.*<\/h3>/s', $html );
+	}
+
 	/**
 	 * Tests completed task count as it completes one by one
 	 */
diff --git a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-test.php b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-test.php
index 58becad8df2..1f0ff3b42de 100644
--- a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-dashboard-test.php
@@ -55,6 +55,7 @@ class WC_Admin_Dashboard_Test extends WC_Unit_Test_Case {
 		delete_option( 'woocommerce_task_list_complete' );
 		remove_all_filters( 'pre_option_woocommerce_task_list_complete' );
 		remove_all_filters( 'pre_option_woocommerce_task_list_hidden' );
+		delete_option( 'woocommerce_enable_reviews' );

 		parent::tearDown();
 	}
@@ -98,18 +99,181 @@ class WC_Admin_Dashboard_Test extends WC_Unit_Test_Case {
 	}

 	/**
-	 * @testdox Widget does not show when neither complete nor hidden.
+	 * @testdox Widget shows when task list is incomplete.
 	 */
-	public function test_widget_does_not_show_when_neither_complete_nor_hidden(): void {
+	public function test_widget_shows_when_task_list_is_incomplete(): void {
 		delete_option( 'woocommerce_task_list_completed_lists' );
 		delete_option( 'woocommerce_task_list_hidden_lists' );

-		$this->assertFalse(
+		$this->assertTrue(
 			$this->invoke_should_display_widget( $this->sut ),
-			'Widget should not display when task list is neither complete nor hidden'
+			'Widget should display even when the task list is incomplete'
+		);
+	}
+
+	/**
+	 * @testdox WooCommerce widgets are registered high in the normal dashboard column in their current order.
+	 */
+	public function test_init_registers_woocommerce_widgets_in_high_normal_context_in_current_order(): void {
+		global $wp_meta_boxes;
+
+		require_once ABSPATH . 'wp-admin/includes/dashboard.php';
+		set_current_screen( 'dashboard' );
+		update_option( 'woocommerce_enable_reviews', 'yes' );
+		unset( $wp_meta_boxes['dashboard'] );
+
+		add_meta_box(
+			'wc_admin_dashboard_setup',
+			'WooCommerce Setup',
+			'__return_empty_string',
+			'dashboard',
+			'normal',
+			'high'
+		);
+		$this->sut->init();
+
+		$this->assertArrayHasKey( 'wc_admin_dashboard_setup', $wp_meta_boxes['dashboard']['normal']['high'] );
+		$this->assertArrayHasKey( 'woocommerce_dashboard_status', $wp_meta_boxes['dashboard']['normal']['high'] );
+		$this->assertArrayHasKey( 'woocommerce_dashboard_recent_reviews', $wp_meta_boxes['dashboard']['normal']['high'] );
+
+		$widget_order = array_values(
+			array_intersect(
+				array_keys( $wp_meta_boxes['dashboard']['normal']['high'] ),
+				array(
+					'wc_admin_dashboard_setup',
+					'woocommerce_dashboard_status',
+					'woocommerce_dashboard_recent_reviews',
+				)
+			)
+		);
+
+		$this->assertSame(
+			array(
+				'wc_admin_dashboard_setup',
+				'woocommerce_dashboard_status',
+				'woocommerce_dashboard_recent_reviews',
+			),
+			$widget_order
 		);
 	}

+	/**
+	 * @testdox Recent reviews widget is not registered when product reviews are disabled.
+	 */
+	public function test_init_does_not_register_recent_reviews_widget_when_reviews_are_disabled(): void {
+		global $wp_meta_boxes;
+
+		require_once ABSPATH . 'wp-admin/includes/dashboard.php';
+		set_current_screen( 'dashboard' );
+		update_option( 'woocommerce_enable_reviews', 'no' );
+		$had_comments_support = post_type_supports( 'product', 'comments' );
+		add_post_type_support( 'product', 'comments' );
+		unset( $wp_meta_boxes['dashboard'] );
+
+		try {
+			$this->sut->init();
+
+			$this->assertArrayHasKey( 'woocommerce_dashboard_status', $wp_meta_boxes['dashboard']['normal']['high'] );
+			$this->assertArrayNotHasKey( 'woocommerce_dashboard_recent_reviews', $wp_meta_boxes['dashboard']['normal']['high'] );
+		} finally {
+			if ( ! $had_comments_support ) {
+				remove_post_type_support( 'product', 'comments' );
+			}
+		}
+	}
+
+	/**
+	 * @testdox Recent reviews widget is registered when product reviews are enabled.
+	 */
+	public function test_init_registers_recent_reviews_widget_when_reviews_are_enabled(): void {
+		global $wp_meta_boxes;
+
+		require_once ABSPATH . 'wp-admin/includes/dashboard.php';
+		set_current_screen( 'dashboard' );
+		update_option( 'woocommerce_enable_reviews', 'yes' );
+		$had_comments_support = post_type_supports( 'product', 'comments' );
+		add_post_type_support( 'product', 'comments' );
+		unset( $wp_meta_boxes['dashboard'] );
+
+		try {
+			$this->sut->init();
+
+			$this->assertArrayHasKey( 'woocommerce_dashboard_recent_reviews', $wp_meta_boxes['dashboard']['normal']['high'] );
+		} finally {
+			if ( ! $had_comments_support ) {
+				remove_post_type_support( 'product', 'comments' );
+			}
+		}
+	}
+
+	/**
+	 * @testdox Recent reviews widget uses the enabled default when the reviews setting has not been saved.
+	 */
+	public function test_init_registers_recent_reviews_widget_when_reviews_setting_is_missing(): void {
+		global $wp_meta_boxes;
+
+		require_once ABSPATH . 'wp-admin/includes/dashboard.php';
+		set_current_screen( 'dashboard' );
+		delete_option( 'woocommerce_enable_reviews' );
+		$had_comments_support = post_type_supports( 'product', 'comments' );
+		add_post_type_support( 'product', 'comments' );
+		unset( $wp_meta_boxes['dashboard'] );
+
+		try {
+			$this->sut->init();
+
+			$this->assertArrayHasKey( 'woocommerce_dashboard_recent_reviews', $wp_meta_boxes['dashboard']['normal']['high'] );
+		} finally {
+			if ( ! $had_comments_support ) {
+				remove_post_type_support( 'product', 'comments' );
+			}
+		}
+	}
+
+	/**
+	 * @testdox Status widget loading placeholder renders the spinner above the loading text.
+	 */
+	public function test_status_widget_loading_placeholder_renders_stacked_loader(): void {
+		wp_deregister_script( 'wc-flot' );
+
+		ob_start();
+		$this->sut->status_widget();
+		$html = ob_get_clean();
+
+		$this->assertTrue( wp_script_is( 'wc-flot', 'registered' ) );
+		$this->assertStringContainsString( 'class="wc-dashboard-widget-loading wc-status-widget-loading"', $html );
+		$this->assertStringContainsString( 'aria-busy="true"', $html );
+		$this->assertStringContainsString( '<p><span class="spinner is-active"></span><span class="wc-dashboard-widget-loading__text">Loading status data...</span></p>', $html );
+	}
+
+	/**
+	 * @testdox Recent reviews widget loading placeholder renders the spinner above the loading text.
+	 */
+	public function test_recent_reviews_widget_loading_placeholder_renders_stacked_loader(): void {
+		ob_start();
+		$this->sut->recent_reviews();
+		$html = ob_get_clean();
+
+		$this->assertStringContainsString( 'class="wc-dashboard-widget-loading wc-recent-reviews-widget-loading"', $html );
+		$this->assertStringContainsString( 'aria-busy="true"', $html );
+		$this->assertStringContainsString( '<p><span class="spinner is-active"></span><span class="wc-dashboard-widget-loading__text">Loading reviews data...</span></p>', $html );
+	}
+
+	/**
+	 * @testdox Status widget order rows render labels before counts.
+	 */
+	public function test_status_widget_order_rows_render_labels_before_counts(): void {
+		$method = new ReflectionMethod( WC_Admin_Dashboard::class, 'status_widget_order_rows' );
+		$method->setAccessible( true );
+
+		ob_start();
+		$method->invoke( $this->sut );
+		$html = ob_get_clean();
+
+		$this->assertStringContainsString( 'Awaiting processing <strong>0 orders</strong>', $html );
+		$this->assertStringContainsString( 'On-hold <strong>0 orders</strong>', $html );
+	}
+
 	/**
 	 * @testdox Widget does not show without proper capabilities.
 	 */