docs(search): force Algolia DocSearch modal to autofocus its input on Cmd+K#202
Draft
mateo-berri wants to merge 1 commit into
Draft
docs(search): force Algolia DocSearch modal to autofocus its input on Cmd+K#202mateo-berri wants to merge 1 commit into
mateo-berri wants to merge 1 commit into
Conversation
… Cmd+K
The Algolia DocSearch modal is loaded via a dynamic import and rendered
into a portal that is prepended to document.body. The input is marked
with React's autoFocus, but in practice the call sometimes loses the
race against:
- the modal portal being inserted before the previously active
element (which can immediately re-assert focus), and
- third-party scripts on the page reacting to body mutations
(e.g. the Crisp chat widget loaded via the cripchat plugin).
Result: the modal opens but the caret never lands in the search input,
and the user has to click the input before they can type. The bug is
intermittent — sometimes autoFocus wins the race, sometimes it loses.
Add a client module that runs a MutationObserver on document.body for
the lifetime of the page. Whenever a .DocSearch-Container element is
inserted, schedule three idempotent focus attempts on its
.DocSearch-Input (synchronous, next animation frame, and 60ms later)
and place the caret at the end of any pre-filled query.
Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Per Mik's report on the eng channel after the Algolia migration: when a user hits
Cmd+Kon the docs site, the search modal opens but the cursor doesn't appear in the search box — the user has to click the input before they can start typing. The behavior is intermittent: sometimes the caret is in the right place, sometimes it isn't.Root cause
@docusaurus/theme-search-algoliarenders the DocSearch modal like this:Two things make autofocus racy:
import()on first invocation, so the modal mounts asynchronously after the keydown event.document.body(document.body.insertBefore(divElement, document.body.firstChild)).The modal input has React's
autoFocus, which schedules a.focus()call after mount. That call sometimes loses the race against:cripchatplugin).Result: the modal renders but the input is never focused, until the user clicks it.
Fix
Add a small client module (
src/clientModules/algoliaSearchAutofocus.js) that runs on every page and:MutationObserverondocument.bodyfor the lifetime of the page..DocSearch-Containerelement is inserted, schedules three idempotent focus attempts on its.DocSearch-Input— synchronous, next animation frame, and 60 ms later — so the input ends up focused even if something else stole focus during the React commit phase.Each attempt is a no-op if the input is already focused, so this never fights React's own
autoFocuswhen it wins the race on the first try.Wired up via the top-level
clientModulesarray indocusaurus.config.js(see Docusaurus client modules docs).Verification
npm run buildsucceeds (broken-anchor warnings onrelease_notes/*are pre-existing).MutationObserverand the.DocSearch-Container/.DocSearch-Inputselectors, confirming the module is wired up and ships to clients.autoFocusalready worked, our.focus()calls are no-ops, so there is no risk of regressing the case where focus is already correct.Slack Thread