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.