Repository navigation
Conversation
Disabled hooks used to keep their mousedown/touchstart/keydown listeners on the document so that components enabling the hook mid-click (e.g. a Flyout with focus trigger opening on mousedown) would still know the mousedown happened inside. A single shared listener now records the last mousedown target, and the hook checks it when it gets enabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SM7EVWJmvGVrdoX9HATtZR
size-limit report 📦
|
…ed mousedown listener Drops the module-level mousedown tracking. When the hook gets enabled it doesn't know where the last mousedown happened yet, so until the next mousedown it checks the click target against the refs instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SM7EVWJmvGVrdoX9HATtZR
This branch has not been deployed
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.
Summary
Issue.
useOnClickOutsideadded itsmousedown/touchstart/keydowndocument listeners whateverdisabledwas, and checkeddisabledonly in the click handler. The comment gave the reason: "some components can enable the hook after it was clicked". The case it protects is aFlyoutwithtriggerType="focus", whichAutocompleteuses. The mousedown on the trigger focuses it, the focus opens the flyout, and that enables the hook. The hook then has to know the press started inside, or theclickthat follows would close the flyout straight away.The cost is that every disabled instance still adds 3 document listeners, and each one runs on every mousedown and keypress on the page. This was found while profiling a 5,000-row menu in Silo (reshaped-ui/silo#104). Every row's editable title calls the hook with
disabled: !editing. Adding those listeners took about 10% of the menu's mount time, and every click then ran thousands of handlers that did nothing.Fix.
isMouseDownInsideRefis reset tonull, meaning no mousedown has been seen since it was enabled. Until the next mousedown, the click handler checks the click's own target against the refs instead, so a click that started inside before the hook was enabled still counts as inside.Tests (Storybook play tests in
useOnClickOutside.stories.tsx):test: disabled doesn't add listeners: mounts 10 disabled hooks and checks that none of the hook's event types get a document listener. It fails on the old hook.test: enabled during click inside: the hook is enabled on an input'sonFocus. Clicking the input must not count as an outside click, and a later click on the body must call the handler. It fails without the click-target fallback.Also adds a patch changeset.
Related Issue
Found while profiling reshaped-ui/silo#104.
Screenshots / Recordings
N/A, no UI changes.
Notes for Reviewers
document. The click then counts as outside.Autocompleteinput. The list stays open with this change and closes when the hook only returns early. The existing Autocomplete tests don't click into the input.pnpm lint:js,oxfmt --checkon the changed files, thetsctypechecks,pnpm test:unitand the full browser suite all pass. The only browser failure wasImageonLoad, which loads an image from unsplash.com and could not reach it from the sandbox.🤖 Generated with Claude Code
https://claude.ai/code/session_01SM7EVWJmvGVrdoX9HATtZR