feat(ui): add Cmd+K global search modal for issues and profiles#191
Conversation
|
Someone is attempting to deploy a commit to the codersogs-3057's projects Team on Vercel. A member of the Team first needs to authorize it. |
# Conflicts: # package-lock.json
Siddhartha-singh01
left a comment
There was a problem hiding this comment.
Nice clean implementation @Krirox auth check is right, the drizzle ilike
parameterization means no SQL injection (I verified), and the cmdk + radix-dialog +
useTransition + 300ms debounce is exactly the right UX pattern. Cleanup on close is
good too.
A few things before this can merge:
-
No rate limit. Every other server action in this repo rate-limits recs:get,
recs:claim, profile:update, maint:queue, etc. searchGlobal should too. Without
it, an authenticated user can enumerate every github_handle in the system by
iterating 2-char prefixes (debouncing on the client doesn't stop direct calls).
Please add:const limited = await rateLimit({ namespace: 'search', key: user.id, limit: 30, windowSec: 60, }); if (!limited.ok) return err('rate_limited', 'slow down', true); -
Tests. This is a testable server action just like recommendations.test.ts
please mock supabase/db and cover the auth-fail, empty-query, and result-shape
paths. Small file, would be a quick addition. -
Escape ILIKE wildcards.
%and_in user input are still treated as
wildcards, soa%searches "starts with a-then-anything" instead of literal
a%. Not a security issue (it's parameterized), but a UX one. Escape\,%,
_in cleanQuery before wrapping with%. -
Add an ORDER BY. Results are in undefined order right now feels random.
Order by id desc, or at least something stable, so the top 5 isn't arbitrary. -
Radix Dialog needs a
Dialog.Title. Radix logs an accessibility warning
when DialogContent has no Title. Add a visually-hidden title for screen
readers it's a couple of lines.
Once the rate limit is in and there's a basic test, this is good to merge. Solid
work overall
Siddhartha-singh01
left a comment
There was a problem hiding this comment.
Excellent follow-up @Krirox all five points are cleanly addressed:
- Rate limit added with the exact shape suggested (search namespace, 30/60s,
retryable: true) ✅ escapeIlikecorrectly escapes , %, _ in the right order (backslash first) ✅- ORDER BY on both queries desc(id) for issues, desc(level) for profiles
stable and semantic ✅ - DialogTitle with
sr-onlyfor the screen-reader requirement ✅ - search.test.ts is genuinely well-built 9 tests covering unauthorized,
no_supabase, rate_limited, short query, whitespace, happy path, empty results,
DB error, AND a "rate limit called with correct args" assertion. The vi.hoisted
pattern and mock chain match the repo's existing test conventions.
Once CI / check goes green on this latest commit, this is ready to merge. Great
work polishing this one through
LGTM ✅
Summary
This PR introduces a global Command Palette (Cmd+K) search feature, allowing users to quickly search across both issues and contributor profiles directly from the UI. It includes the frontend interface using
cmdkand a server action to query the database efficiently.Type of Change
Related Issue
Closes #164
What was changed?
src/components/command-palette.tsx, a new reusable command palette component triggered byCmd+K/Ctrl+K.@radix-ui/react-dialogandcmdkfor an accessible, keyboard-first search experience.searchGlobalserver action insrc/app/actions/search.tsto perform fast, case-insensitive (ilike) database queries acrossissues(by title) andprofiles(by GitHub handle).Screenshots
Checklist
npm run dev)