diff --git a/.changeset/rnd-11849-search-focus-hydration.md b/.changeset/rnd-11849-search-focus-hydration.md new file mode 100644 index 000000000..5478a8110 --- /dev/null +++ b/.changeset/rnd-11849-search-focus-hydration.md @@ -0,0 +1,5 @@ +--- +"gitbook": patch +--- + +Fix the search field losing focus if it was focused just before the page finished hydrating. diff --git a/packages/gitbook/src/components/Search/SearchInput.tsx b/packages/gitbook/src/components/Search/SearchInput.tsx index 6aa5fc090..4ffcf1746 100644 --- a/packages/gitbook/src/components/Search/SearchInput.tsx +++ b/packages/gitbook/src/components/Search/SearchInput.tsx @@ -46,11 +46,22 @@ export const SearchInput = React.forwardRef( } = props; const inputRef = useRef(null); const isFrame = mode === 'frame'; + const isInitialMountRef = useRef(true); const language = useLanguage(); useEffect(() => { + const isInitialMount = isInitialMountRef.current; + isInitialMountRef.current = false; + if (!isOpen) { + // A user can focus the SSR'd input natively before hydration attaches + // React's focus handler; syncing to "open" instead of blurring avoids + // stealing that focus back on mount. + if (isInitialMount && document.activeElement === inputRef.current) { + onFocus?.(); + return; + } inputRef.current?.blur(); return; } @@ -69,7 +80,7 @@ export const SearchInput = React.forwardRef( const timeout = window.setTimeout(focusInput, 150); return () => window.clearTimeout(timeout); - }, [isFrame, isOpen, value.length]); + }, [isFrame, isOpen, value.length, onFocus]); return (