Skip to content

Fixes for cmd+k search palette#846

Open
shaneikennedy wants to merge 2 commits intoTanStack:mainfrom
shaneikennedy:main
Open

Fixes for cmd+k search palette#846
shaneikennedy wants to merge 2 commits intoTanStack:mainfrom
shaneikennedy:main

Conversation

@shaneikennedy
Copy link
Copy Markdown

@shaneikennedy shaneikennedy commented Apr 22, 2026

  1. When you use the search palette to find a bunch of things and want to open them all with cmd+click, the first cmd+click closes the search palette
  2. cmd+k should put the focus on the search input so you can start typing right away

Summary by CodeRabbit

  • Bug Fixes
    • Improved search modal behavior: modifier keys (Cmd, Ctrl, Shift, Alt) are now respected when clicking search results, allowing users to open results in new tabs or windows without closing the modal.
    • Enhanced search input focus management for better keyboard accessibility when opening the search modal.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 22, 2026

👷 Deploy request for tanstack pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 5cb8849

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9cebd3aa-985d-475a-a6a3-41b0ab319ba7

📥 Commits

Reviewing files that changed from the base of the PR and between eb49d0e and 5cb8849.

📒 Files selected for processing (1)
  • src/components/SearchModal.tsx
 ______________________________________________________________
< I had to scroll so far I hit the heat death of the universe. >
 --------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can scan for known vulnerabilities in your dependencies using OSV Scanner.

OSV Scanner will automatically detect and report security vulnerabilities in your project's dependencies. No additional configuration is required.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/components/SearchModal.tsx (1)

424-429: Consider also guarding non-primary mouse buttons.

The modifier-key check covers cmd/ctrl/shift/alt + click, but middle-click (event.button === 1) also opens links in a new tab on most browsers and will currently close the palette. If you want the "open multiple results" flow to be consistent across input methods, include a button check:

-    if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
+    if (
+      event.button !== 0 ||
+      event.metaKey ||
+      event.ctrlKey ||
+      event.shiftKey ||
+      event.altKey
+    ) {
       return
     }

Note: many browsers now dispatch auxclick instead of click for middle-button, so this is defensive rather than strictly necessary.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/SearchModal.tsx` around lines 424 - 429, The click handler
handleClick currently only checks modifier keys and should also ignore
non-primary mouse buttons so middle-clicks don't close the search; update
handleClick to short-circuit when event.button !== 0 (or explicitly check for
event.button === 1) before calling closeSearch, and add or wire an auxclick
handler mirroring the same guard (so middle-button/Aux clicks are consistently
ignored). Refer to handleClick, closeSearch and the auxclick event when making
the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/SearchModal.tsx`:
- Around line 785-800: The effect that focuses the search input schedules two
nested requestAnimationFrame calls but only cancels the outer id; update the
effect (useEffect in SearchModal.tsx) to capture both the outer and inner
requestAnimationFrame ids (e.g., idOuter and idInner) when scheduling
focusSearchInput (which uses containerRef and
querySelector('input[type="search"]')) and cancel both in the cleanup via
window.cancelAnimationFrame(idOuter) and window.cancelAnimationFrame(idInner) so
the inner callback cannot run after the component closes or unmounts.

---

Nitpick comments:
In `@src/components/SearchModal.tsx`:
- Around line 424-429: The click handler handleClick currently only checks
modifier keys and should also ignore non-primary mouse buttons so middle-clicks
don't close the search; update handleClick to short-circuit when event.button
!== 0 (or explicitly check for event.button === 1) before calling closeSearch,
and add or wire an auxclick handler mirroring the same guard (so
middle-button/Aux clicks are consistently ignored). Refer to handleClick,
closeSearch and the auxclick event when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9cebd3aa-985d-475a-a6a3-41b0ab319ba7

📥 Commits

Reviewing files that changed from the base of the PR and between eb49d0e and 5cb8849.

📒 Files selected for processing (1)
  • src/components/SearchModal.tsx

Comment on lines +785 to +800
React.useEffect(() => {
if (!isOpen) return

const focusSearchInput = () => {
const input = containerRef.current?.querySelector<HTMLInputElement>(
'input[type="search"]',
)
input?.focus()
}

const id = window.requestAnimationFrame(() => {
window.requestAnimationFrame(focusSearchInput)
})
return () => window.cancelAnimationFrame(id)
}, [isOpen])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Cleanup only cancels the outer requestAnimationFrame.

If the outer rAF has already fired before the effect cleanup runs (e.g., user closes the palette within ~1 frame of opening, or isOpen toggles quickly), the inner rAF is already scheduled and will still invoke focusSearchInput() — potentially focusing an input that's about to unmount or stealing focus after close. Track the inner id and cancel it as well.

♻️ Proposed fix
-    const id = window.requestAnimationFrame(() => {
-      window.requestAnimationFrame(focusSearchInput)
-    })
-    return () => window.cancelAnimationFrame(id)
+    let innerId = 0
+    const outerId = window.requestAnimationFrame(() => {
+      innerId = window.requestAnimationFrame(focusSearchInput)
+    })
+    return () => {
+      window.cancelAnimationFrame(outerId)
+      if (innerId) window.cancelAnimationFrame(innerId)
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/SearchModal.tsx` around lines 785 - 800, The effect that
focuses the search input schedules two nested requestAnimationFrame calls but
only cancels the outer id; update the effect (useEffect in SearchModal.tsx) to
capture both the outer and inner requestAnimationFrame ids (e.g., idOuter and
idInner) when scheduling focusSearchInput (which uses containerRef and
querySelector('input[type="search"]')) and cancel both in the cleanup via
window.cancelAnimationFrame(idOuter) and window.cancelAnimationFrame(idInner) so
the inner callback cannot run after the component closes or unmounts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant