Commit f0198dc0ce for woocommerce

commit f0198dc0ceac44be11e3c38266260429abd6798a
Author: Chi-Hsuan Huang <chihsuan.tw@gmail.com>
Date:   Mon Jan 12 11:13:50 2026 +0900

    Fix Import Status Bar UI overlap and add loading state (#62675)

    * Enhance Import Status Bar UI and Logic

    * Update styles for the import status bar to improve alignment and responsiveness.
    * Refactor button logic to use a single 'isBusy' state for better clarity.
    * Adjust button display to show a spinner when busy, enhancing user feedback.

    * Update Import Status Bar and Report Header Styles

    * Add width to the import status bar label for improved layout.
    * Enhance accessibility by adding aria attributes to the import trigger button.
    * Update the aria-label to reflect the import status dynamically.
    * Adjust media query breakpoint in report header styles for better responsiveness.

    * Add changefile(s) from automation for the following project(s): woocommerce, woocommerce/client/admin

    * Update import status bar styles to prevent layout shift during loading

    * Add a comment to clarify the purpose of setting a fixed width for the import status bar label.

    * Update import status bar styles for improved responsiveness

    * Change gap values in media queries to use defined variables for better consistency across breakpoints.

    * Fix unit tests for accessibility improvements

    Update tests to use new dynamic aria-label when button is busy:
    - "Analytics data import in progress" instead of "Manually trigger analytics data import"
    - Add assertion for aria-busy attribute

    🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

    * Fix E2E test for updated button aria-label

    Update the analytics-overview E2E test to use the correct button
    aria-label after accessibility improvements. The button now has:
    - Initial state: "Manually trigger analytics data import"
    - Busy state: "Analytics data import in progress"

    🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

    ---------

    Co-authored-by: github-actions <github-actions@github.com>
    Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

diff --git a/plugins/woocommerce/changelog/62675-fix-scheduled-import-ui b/plugins/woocommerce/changelog/62675-fix-scheduled-import-ui
new file mode 100644
index 0000000000..bcda2c5081
--- /dev/null
+++ b/plugins/woocommerce/changelog/62675-fix-scheduled-import-ui
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix Import Status Bar UI overlap with filter dropdowns and add loading state feedback
\ No newline at end of file
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/import-status-bar.scss b/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/import-status-bar.scss
index bf13a265fd..2d1e38084e 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/import-status-bar.scss
+++ b/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/import-status-bar.scss
@@ -9,11 +9,21 @@
 	gap: 6px;

 	&__label {
+		margin: 7px 0 0; // use same margin as filters to they align vertically
 		font-size: 13px;
 		line-height: 20px;
 		color: $gray-900;
 		font-weight: 400;
 	}
+
+	@media screen and ( max-width: $break-large ) {
+		gap: 5px;
+
+		&__label {
+			line-height: 18px;
+			margin-top: 5px;
+		}
+	}
 }

 .woocommerce-analytics-import-status-bar {
@@ -34,7 +44,11 @@


 		@media screen and ( max-width: $break-wide ) {
-			gap: 24px;
+			gap: $gap-large;
+		}
+
+		@media screen and ( max-width: $break-large ) {
+			gap: $gap;
 		}
 	}

@@ -56,6 +70,8 @@
 		font-size: 11px;
 		font-weight: 500;
 		line-height: 20px;
+		// Set a fixed width to prevent layout shift during loading
+		width: 88px;
 	}

 	.components-spinner {
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/import-status-bar.tsx b/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/import-status-bar.tsx
index 2a597f92bf..ee76f8d8bf 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/import-status-bar.tsx
+++ b/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/import-status-bar.tsx
@@ -109,9 +109,7 @@ export function ImportStatusBar(): JSX.Element | null {
 		}
 	};

-	// Disable button when an import is already scheduled/running or currently triggering
-	const isButtonDisabled =
-		status?.import_in_progress_or_due || isTriggeringImport;
+	const isBusy = status?.import_in_progress_or_due || isTriggeringImport;

 	return (
 		<div className="woocommerce-analytics-import-status-bar-wrapper">
@@ -157,15 +155,27 @@ export function ImportStatusBar(): JSX.Element | null {
 					<Button
 						variant="tertiary"
 						onClick={ handleTriggerImport }
-						disabled={ isButtonDisabled || isLoading }
-						isBusy={ isTriggeringImport }
+						disabled={ isLoading || isBusy }
+						aria-disabled={ isLoading || isBusy }
+						aria-busy={ isBusy }
 						className="woocommerce-analytics-import-status-bar__trigger"
-						aria-label={ __(
-							'Manually trigger analytics data import',
-							'woocommerce'
-						) }
+						aria-label={
+							isBusy
+								? __(
+										'Analytics data import in progress',
+										'woocommerce'
+								  )
+								: __(
+										'Manually trigger analytics data import',
+										'woocommerce'
+								  )
+						}
 					>
-						{ __( 'Update now', 'woocommerce' ) }
+						{ isBusy ? (
+							<Spinner />
+						) : (
+							__( 'Update now', 'woocommerce' )
+						) }
 					</Button>
 				</div>
 			</div>
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/test/import-status-bar.test.tsx b/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/test/import-status-bar.test.tsx
index f9c87966e8..3a3ff7f9d0 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/test/import-status-bar.test.tsx
+++ b/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/test/import-status-bar.test.tsx
@@ -138,10 +138,12 @@ describe( 'ImportStatusBar', () => {

 		render( <ImportStatusBar /> );

+		// When busy, aria-label changes to "Analytics data import in progress"
 		const button = screen.getByRole( 'button', {
-			name: /Manually trigger analytics data import/i,
+			name: /Analytics data import in progress/i,
 		} );
 		expect( button ).toBeDisabled();
+		expect( button ).toHaveAttribute( 'aria-busy', 'true' );
 	} );

 	it( 'should disable button when isTriggeringImport is true', () => {
@@ -153,10 +155,12 @@ describe( 'ImportStatusBar', () => {

 		render( <ImportStatusBar /> );

+		// When busy, aria-label changes to "Analytics data import in progress"
 		const button = screen.getByRole( 'button', {
-			name: /Manually trigger analytics data import/i,
+			name: /Analytics data import in progress/i,
 		} );
 		expect( button ).toBeDisabled();
+		expect( button ).toHaveAttribute( 'aria-busy', 'true' );
 	} );

 	it( 'should trigger import on button click', async () => {
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/report-header/report-header.scss b/plugins/woocommerce/client/admin/client/analytics/components/report-header/report-header.scss
index 612b247a34..d98716daf5 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/report-header/report-header.scss
+++ b/plugins/woocommerce/client/admin/client/analytics/components/report-header/report-header.scss
@@ -5,38 +5,53 @@
  */

 .woocommerce-analytics-report-header {
-	position: relative;
-	display: flex;
-	align-items: flex-start;
+	// Only apply this layout when the import status bar is present
+	&:has(> .woocommerce-analytics-import-status-bar-wrapper) {
+		position: relative;
+		display: flex;
+		align-items: flex-start;
+		gap: $gap;

-	.woocommerce-filters {
-		flex: 1; // Allow the filters to grow and take up remaining space
-		width: 100%;
-	}
+		.woocommerce-filters {
+			flex: 1; // Allow the filters to grow and take up remaining space
+			width: 100%;
+		}

-	.woocommerce-analytics-import-status-bar-wrapper {
-		// Absolute positioning ensures the filters’ width is independent from the status bar, which can change its size dynamically as needed
-		position: absolute;
-		right: 0;
-	}
+		.woocommerce-filters-filter {
+			min-width: fit-content;
+		}

-	@media screen and ( max-width: $break-large ) {
-		flex-direction: column;
+		@media screen and ( max-width: $break-wide ) {
+			.woocommerce-filters-filter {
+				width: 100%;
+			}

-		.woocommerce-analytics-import-status-bar-wrapper {
-			position: relative;
-			right: auto;
+			.woocommerce-analytics-import-status-bar-wrapper {
+				flex: 1;
+			}
 		}
-	}

-	@media screen and ( max-width: $break-medium ) {
-		.woocommerce-analytics-import-status-bar-wrapper,
-		.woocommerce-analytics-import-status-bar__content {
-			width: 100%;
+		@media screen and ( max-width: $break-medium ) {
+			flex-direction: column;
+			gap: 0;
+
+			.woocommerce-filters__basic-filters {
+				margin-bottom: $gap;
+			}
+
+			.woocommerce-analytics-import-status-bar-wrapper {
+				margin-bottom: $gap-large;
+				width: 100%;
+			}
+
+			.woocommerce-analytics-import-status-bar__content {
+				width: 100%;
+				justify-content: space-between;
+			}
 		}

-		.woocommerce-analytics-import-status-bar__content {
-			justify-content: space-between;
+		@media screen and ( max-width: $break-small ) {
+			align-items: center;
 		}
 	}
 }
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/analytics/analytics-overview.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/analytics/analytics-overview.spec.js
index 654afe4f2e..91e20bd5c1 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/analytics/analytics-overview.spec.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/analytics/analytics-overview.spec.js
@@ -357,7 +357,7 @@ test.describe(
 			await expect( page.getByText( 'Data status:' ) ).toBeVisible();
 			// Verify "Update now" button is visible
 			const updateButton = page.getByRole( 'button', {
-				name: 'Manually trigger analytics',
+				name: 'Manually trigger analytics data import',
 			} );
 			await expect( updateButton ).toBeVisible();

@@ -373,7 +373,11 @@ test.describe(
 			await updateButton.click();

 			// Verify button shows loading state (isBusy)
-			await expect( updateButton ).toBeDisabled();
+			// After clicking, the aria-label changes to "Analytics data import in progress"
+			const busyButton = page.getByRole( 'button', {
+				name: 'Analytics data import in progress',
+			} );
+			await expect( busyButton ).toBeDisabled();

 			// Wait for API response
 			await responsePromise;