Commit fc7d52a31e0 for woocommerce

commit fc7d52a31e01c06c8ca7721704bd552410b7be60
Author: Albert Juhé Lluveras <contact@albertjuhe.com>
Date:   Mon Oct 19 17:40:02 2026 +0200

    Hide Product Filters overlay contents from tab navigation when the overlay is closed (#69928)

    * Use more semantic HTML tags

    * Harden esc function

    * Ensure closed overlay contents are not visible to screen readers

    * Update tests

    * Add changelog

diff --git a/plugins/woocommerce/changelog/fix-69078-hide-filter-overlay-from-accessibility-tree-when-closed b/plugins/woocommerce/changelog/fix-69078-hide-filter-overlay-from-accessibility-tree-when-closed
new file mode 100644
index 00000000000..77da6db43e4
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-69078-hide-filter-overlay-from-accessibility-tree-when-closed
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Hide Product Filters overlay contents from tab navigation when the overlay is closed
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/edit.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/edit.tsx
index 5d56f4d1126..7241f7af694 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/edit.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/edit.tsx
@@ -112,7 +112,7 @@ export const Edit = ( props: BlockEditProps< BlockAttributes > ) => {

 				<div className="wc-block-product-filters__overlay">
 					<div className="wc-block-product-filters__overlay-wrapper">
-						<div
+						<section
 							className="wc-block-product-filters__overlay-dialog"
 							role="dialog"
 						>
@@ -140,7 +140,7 @@ export const Edit = ( props: BlockEditProps< BlockAttributes > ) => {
 									</span>
 								</button>
 							</footer>
-						</div>
+						</section>
 					</div>
 				</div>
 			</>
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/style.scss b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/style.scss
index 0903db37d64..0f15f069b68 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/style.scss
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/style.scss
@@ -37,8 +37,10 @@
 		top: var(--top-padding);
 		z-index: 9999;
 		background-color: transparent;
-		// Delay the 200ms backdrop fade so it finishes with the 500ms drawer transition.
-		transition: background-color 200ms 300ms;
+		// Inherited visibility removes the closed drawer from the tab order.
+		// Keep it through the 500ms slide, after the 200ms backdrop fade.
+		visibility: hidden;
+		transition: background-color 200ms 300ms, visibility 0s 500ms;
 	}

 	.wc-block-product-filters__overlay-wrapper {
@@ -112,6 +114,7 @@
 	&.is-overlay-opened {
 		.wc-block-product-filters__overlay {
 			pointer-events: auto;
+			visibility: visible;
 			background-color: rgba(95, 95, 95, 0.35);
 			transition-delay: 0s;
 		}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
index bf2501c0c7b..fe9ff651d18 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
@@ -110,6 +110,7 @@ class ProductFilters extends AbstractBlock {
 	:where(.wc-block-product-filters).is-mobile-overlay .wc-block-product-filters__overlay {
 		position: relative;
 		pointer-events: auto;
+		visibility: visible;
 		inset: 0;
 		z-index: auto;
 		background: inherit;
@@ -263,10 +264,10 @@ CSS;
 				</button>
 				<div class="wc-block-product-filters__overlay">
 					<div class="wc-block-product-filters__overlay-wrapper" data-wp-on--click="actions.closeOverlayOnBackdrop">
-						<div
+						<section
 							class="wc-block-product-filters__overlay-dialog"
 							role="dialog"
-							aria-label="<?php echo esc_html__( 'Product Filters', 'woocommerce' ); ?>"
+							aria-label="<?php echo esc_attr__( 'Product Filters', 'woocommerce' ); ?>"
 						>
 							<header class="wc-block-product-filters__overlay-header">
 								<button
@@ -295,7 +296,7 @@ CSS;
 									<span><?php echo esc_html__( 'Apply', 'woocommerce' ); ?></span>
 								</button>
 							</footer>
-						</div>
+						</section>
 					</div>
 				</div>
 			<?php else : ?>
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/product-filters/product-filters-frontend.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/product-filters/product-filters-frontend.block_theme.spec.ts
index 471adbae8f1..861844a5539 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/product-filters/product-filters-frontend.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/product-filters/product-filters-frontend.block_theme.spec.ts
@@ -50,10 +50,12 @@ test.describe( 'woocommerce/product-filters - Frontend', () => {
 			const openOverlayButton = page.getByRole( 'button', {
 				name: 'Filter products',
 			} );
-			const overlay = page.getByRole( 'dialog' );
+			const overlay = page.getByRole( 'dialog', {
+				name: 'Product Filters',
+			} );

 			await expect( openOverlayButton ).toBeVisible();
-			await expect( overlay ).not.toBeInViewport();
+			await expect( overlay ).toHaveCount( 0 );

 			await openOverlayButton.click();

@@ -68,7 +70,7 @@ test.describe( 'woocommerce/product-filters - Frontend', () => {

 			await closeOverlayButton.click();

-			await expect( overlay ).not.toBeInViewport();
+			await expect( overlay ).toHaveCount( 0 );

 			// Close overlay by hitting Esc.
 			await openOverlayButton.click();
@@ -77,7 +79,7 @@ test.describe( 'woocommerce/product-filters - Frontend', () => {

 			await page.keyboard.press( 'Escape' );

-			await expect( overlay ).not.toBeInViewport();
+			await expect( overlay ).toHaveCount( 0 );

 			// Close overlay by clicking Apply button.
 			await openOverlayButton.click();
@@ -92,7 +94,7 @@ test.describe( 'woocommerce/product-filters - Frontend', () => {

 			await applyButton.click();

-			await expect( overlay ).not.toBeInViewport();
+			await expect( overlay ).toHaveCount( 0 );
 		} );

 		// Skipping these tests until we can move this block to @wordpress/interactivity.