diff --git a/src/theme/SearchBar/index.js b/src/theme/SearchBar/index.js
index 7e9ba1b1aea..595140b1c5e 100644
--- a/src/theme/SearchBar/index.js
+++ b/src/theme/SearchBar/index.js
@@ -1,4 +1,4 @@
-import React, { useCallback, useMemo, useRef, useState } from 'react';
+import React, { useCallback, useMemo, useRef, useState, useEffect } from 'react';
import { DocSearchButton, useDocSearchKeyboardEvents } from '@docsearch/react';
import Head from '@docusaurus/Head';
import { useHistory } from '@docusaurus/router';
@@ -9,7 +9,6 @@ import {
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { createPortal } from 'react-dom';
import translations from '@theme/SearchTranslations';
-import { useEffect } from 'react';
import {useAskAI} from '@site/src/hooks/useAskAI'
import { shouldPreventSearchAction, handleSearchKeyboardConflict } from './utils/aiConflictHandler';
import { initializeSearchAnalytics, createEnhancedSearchClient } from './utils/searchAnalytics';
@@ -25,17 +24,17 @@ import { DocTypeSelector } from './docTypeSelector';
function DocSearch({ contextualSearch, externalUrlRegex, ...props }) {
const queryIDRef = useRef(null);
+ const lastQueryRef = useRef('');
const { siteMetadata, i18n: { currentLocale } } = useDocusaurusContext();
const processSearchResultUrl = useSearchResultUrlProcessor();
const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters();
- const { isAskAIOpen, currentMode } = useAskAI();
+ const { isAskAIOpen } = useAskAI();
const history = useHistory();
const searchButtonRef = useRef(null);
- // Doc type filtering state
const [selectedDocTypes, setSelectedDocTypes] = useState(null);
+ const searchParametersRef = useRef(null);
- // Use the modal management hook
const {
isOpen,
initialQuery,
@@ -47,26 +46,63 @@ function DocSearch({ contextualSearch, externalUrlRegex, ...props }) {
importDocSearchModalIfNeeded
} = useDocSearchModal();
- // Configure search parameters with doc_type filter
- const searchParameters = createSearchParameters(
- props,
- contextualSearch,
- contextualSearchFacetFilters,
- selectedDocTypes
- );
+ // Update searchParameters ref instead of creating new object
+ useEffect(() => {
+ const newParams = createSearchParameters(
+ props,
+ contextualSearch,
+ contextualSearchFacetFilters,
+ selectedDocTypes
+ );
+
+ if (!searchParametersRef.current) {
+ searchParametersRef.current = newParams;
+ } else {
+ Object.keys(newParams).forEach(key => {
+ searchParametersRef.current[key] = newParams[key];
+ });
+ }
+ }, [props, contextualSearch, contextualSearchFacetFilters, selectedDocTypes]);
+
+ // Initialize on mount
+ if (!searchParametersRef.current) {
+ searchParametersRef.current = createSearchParameters(
+ props,
+ contextualSearch,
+ contextualSearchFacetFilters,
+ selectedDocTypes
+ );
+ }
+
+ // Track input changes to capture the query
+ useEffect(() => {
+ if (!isOpen) return;
+
+ const handleInput = (e) => {
+ const input = e.target;
+ if (input.classList.contains('DocSearch-Input')) {
+ lastQueryRef.current = input.value;
+ }
+ };
+
+ document.addEventListener('input', handleInput, true);
+ return () => document.removeEventListener('input', handleInput, true);
+ }, [isOpen]);
useEffect(() => {
initializeSearchAnalytics(props.appId, props.apiKey);
}, [props.appId, props.apiKey]);
- // Create navigator for handling result clicks
const navigator = useMemo(
() => createSearchNavigator(history, externalUrlRegex),
[history, externalUrlRegex]
);
- // Transform search items with metadata
const transformItems = useCallback((items, state) => {
+ if (state?.query) {
+ lastQueryRef.current = state.query;
+ }
+
return transformSearchItems(items, {
transformItems: props.transformItems,
processSearchResultUrl,
@@ -75,36 +111,74 @@ function DocSearch({ contextualSearch, externalUrlRegex, ...props }) {
});
}, [props.transformItems, processSearchResultUrl, currentLocale]);
- const handleDocTypeChange = useCallback((docTypes) => {
- setSelectedDocTypes(docTypes);
- }, []);
+const handleDocTypeChange = useCallback((docTypes) => {
+ setSelectedDocTypes(docTypes);
+
+ // Re-trigger search with updated filters after state update completes
+ setTimeout(() => {
+ const input = document.querySelector('.DocSearch-Input');
+ const query = lastQueryRef.current;
+
+ if (input && query) {
+ // Access React's internal value setter to bypass readonly property
+ const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
+ window.HTMLInputElement.prototype,
+ 'value'
+ ).set;
+
+ // Clear input to trigger change detection
+ nativeInputValueSetter.call(input, '');
+ input.dispatchEvent(new Event('input', { bubbles: true }));
+
+ // Restore original query to execute search with new filters
+ setTimeout(() => {
+ nativeInputValueSetter.call(input, query);
+ input.dispatchEvent(new Event('input', { bubbles: true }));
+ input.focus();
+ }, 0);
+ }
+ }, 100);
+}, []);
const resultsFooterComponent = useMemo(
- () =>
- // eslint-disable-next-line react/no-unstable-nested-components
- (footerProps) =>
-