From db2253ef5eb7987d1df3c777fc6781fb5195dc16 Mon Sep 17 00:00:00 2001 From: Dan Piazza <220388267+DanPiazza-Netwrix@users.noreply.github.com> Date: Wed, 11 Mar 2026 11:49:21 -0400 Subject: [PATCH 1/3] Change product filter memory from localStorage to sessionStorage --- src/theme/SearchBar/index.js | 6 +++--- src/theme/SearchPage/index.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/theme/SearchBar/index.js b/src/theme/SearchBar/index.js index 648906de38..a3ac2ac8b5 100644 --- a/src/theme/SearchBar/index.js +++ b/src/theme/SearchBar/index.js @@ -492,7 +492,7 @@ export default function SearchBar() { // Multi-select state for products const [selectedProducts, setSelectedProducts] = useState(() => { if (typeof window === 'undefined') return []; - const saved = localStorage.getItem('docs_product_filter'); + const saved = sessionStorage.getItem('docs_product_filter'); try { return saved ? JSON.parse(saved) : []; } catch { @@ -507,10 +507,10 @@ export default function SearchBar() { selectedProductsRef.current = selectedProducts; }, [selectedProducts]); - // Sync selectedProducts to localStorage and dispatch custom event for same-tab sync + // Sync selectedProducts to sessionStorage and dispatch custom event for same-tab sync useEffect(() => { if (typeof window !== 'undefined') { - localStorage.setItem('docs_product_filter', JSON.stringify(selectedProducts)); + sessionStorage.setItem('docs_product_filter', JSON.stringify(selectedProducts)); // Dispatch custom event for same-tab synchronization window.dispatchEvent(new CustomEvent('productFilterChange', { detail: {products: selectedProducts} diff --git a/src/theme/SearchPage/index.js b/src/theme/SearchPage/index.js index f85cf6897a..d619975f3a 100644 --- a/src/theme/SearchPage/index.js +++ b/src/theme/SearchPage/index.js @@ -237,7 +237,7 @@ function SearchPageContent() { const [selectedProducts, setSelectedProducts] = useState(() => { if (productsFromUrl.length > 0) return productsFromUrl; if (typeof window === 'undefined') return []; - const saved = localStorage.getItem('docs_product_filter'); + const saved = sessionStorage.getItem('docs_product_filter'); try { return saved ? JSON.parse(saved) : []; } catch { @@ -251,10 +251,10 @@ function SearchPageContent() { const targetPageRef = useRef(null); const isInternalNavigation = useRef(false); - // Sync selectedProducts to localStorage and dispatch custom event for same-tab sync + // Sync selectedProducts to sessionStorage and dispatch custom event for same-tab sync useEffect(() => { if (typeof window !== 'undefined') { - localStorage.setItem('docs_product_filter', JSON.stringify(selectedProducts)); + sessionStorage.setItem('docs_product_filter', JSON.stringify(selectedProducts)); // Dispatch custom event for same-tab synchronization window.dispatchEvent(new CustomEvent('productFilterChange', { detail: {products: selectedProducts} From 0129d57df8f04ab1391b663091ac8f3d4f68f99e Mon Sep 17 00:00:00 2001 From: Dan Piazza <220388267+DanPiazza-Netwrix@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:10:58 -0400 Subject: [PATCH 2/3] Search modal now updates results in real time as filters are changed --- src/theme/SearchBar/index.js | 44 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/theme/SearchBar/index.js b/src/theme/SearchBar/index.js index 648906de38..531b4f39e8 100644 --- a/src/theme/SearchBar/index.js +++ b/src/theme/SearchBar/index.js @@ -558,38 +558,44 @@ export default function SearchBar() { return () => clearInterval(interval); }, []); - // Helper to refresh search - preserve query and wait for user action + // Helper to refresh search results with current filters. + // DocSearch uses React-controlled inputs, so plain native input events don't trigger + // its onChange handler. We use React's native HTMLInputElement value setter to bypass + // React's change-tracking wrapper, then dispatch an input event so React processes it. const refreshSearch = useCallback(() => { const input = document.querySelector('.DocSearch-Input') || document.querySelector('input[type="search"]'); - if (input && input.value) { - searchQueryRef.current = input.value; + if (!input || !input.value) return; - // Try multiple approaches to trigger search - const query = input.value; + const query = input.value; + searchQueryRef.current = query; + + // Grab the native setter before React wraps it + const nativeSetter = Object.getOwnPropertyDescriptor( + window.HTMLInputElement.prototype, + 'value', + ).set; + + // Simulate typing a trailing space and removing it. + // This causes DocSearch/Autocomplete to run a new search with the updated filters. + setTimeout(() => { + nativeSetter.call(input, query + ' '); + input.dispatchEvent(new Event('input', {bubbles: true})); - // Approach 1: Simulate typing by adding/removing character setTimeout(() => { - if (input) { - input.value = query + ' '; - input.dispatchEvent(new Event('input', {bubbles: true})); - - setTimeout(() => { - input.value = query; - input.dispatchEvent(new Event('input', {bubbles: true})); - input.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })); - }, 50); - } + nativeSetter.call(input, query); + input.dispatchEvent(new Event('input', {bubbles: true})); }, 50); - } + }, 50); }, []); const onChangeProducts = useCallback((newProducts) => { + selectedProductsRef.current = newProducts; // Sync ref immediately so search uses new filters setSelectedProducts(newProducts); - // localStorage and event dispatch handled by useEffect - }, []); + refreshSearch(); // Re-run current query with updated filters + }, [refreshSearch]); // This is where we will portal the filters into the modal DOM. const [modalHeaderEl, setModalHeaderEl] = useState(null); From ac8e5181be92e357b1666eaa2197b42f7313fb1d Mon Sep 17 00:00:00 2001 From: Dan Piazza <220388267+DanPiazza-Netwrix@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:03:08 -0400 Subject: [PATCH 3/3] Fix 50ms delay in modal result display causing brief visual glitch --- src/theme/SearchBar/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/theme/SearchBar/index.js b/src/theme/SearchBar/index.js index 531b4f39e8..e4280278bc 100644 --- a/src/theme/SearchBar/index.js +++ b/src/theme/SearchBar/index.js @@ -580,14 +580,14 @@ export default function SearchBar() { // Simulate typing a trailing space and removing it. // This causes DocSearch/Autocomplete to run a new search with the updated filters. + // Both events fire in the same JS task so DocSearch batches them — only the final + // value (query) triggers a visible search, preventing an intermediate result flash. setTimeout(() => { nativeSetter.call(input, query + ' '); input.dispatchEvent(new Event('input', {bubbles: true})); - setTimeout(() => { - nativeSetter.call(input, query); - input.dispatchEvent(new Event('input', {bubbles: true})); - }, 50); + nativeSetter.call(input, query); + input.dispatchEvent(new Event('input', {bubbles: true})); }, 50); }, []);