feat: add semantic settings search#1687
Conversation
- Add useSettingsSearch hook for indexing and searching settings - Add SettingsSearchInput and SettingsSearchResults components - Integrate search into SettingsPage with highlight and scroll-to behavior - Add search metadata to all settings cards for indexability - Add integration registry for searchable integration entries - Add unit tests for settings search index
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughAdds an in-app settings search with keyboard shortcut and scroll-to, centralizes integrations metadata, adds stable DOM IDs to many settings cards, refactors git-status parsing into helpers, restructures terminal input/submission and write-drain scheduling, and adds tests validating the settings/integrations index. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant Page as SettingsPage
participant Input as SettingsSearchInput
participant Search as useSettingsSearch
participant Results as SettingsSearchResults
participant DOM as DOM
User->>Input: Cmd/Ctrl+F / type query
Input->>Page: onQueryChange(query)
Page->>Search: searchSettings(trimmedQuery)
Search-->>Page: results[]
Page->>Results: render results
User->>Results: click result
Results->>Page: onResultClick(tabId, elementId)
Page->>Page: switch tab, clear query
Page->>DOM: render tab content
Page->>DOM: element.scrollIntoView()
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (4)
src/renderer/components/SettingsSearchInput.tsx (2)
15-20: Minor: Consider calling.select()after.focus()for consistency with Cmd/Ctrl+F behavior.The Cmd/Ctrl+F handler in
SettingsPagecalls bothfocus()andselect(), buthandleClearonly callsfocus(). This creates a subtle UX difference: after pressing Cmd+F the text is selected, but after clicking clear it is not. This is a minor inconsistency.♻️ Optional fix for consistency
const handleClear = () => { onQueryChange(''); if (ref && typeof ref === 'object') { ref.current?.focus(); + ref.current?.select(); } };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/renderer/components/SettingsSearchInput.tsx` around lines 15 - 20, handleClear currently calls onQueryChange('') and then ref.current?.focus() which leaves the input unselected; change it to also call ref.current?.select() after focus so clearing mirrors the Cmd/Ctrl+F behavior in SettingsPage. Update the handleClear function (and any related refs used for the input) to call focus() followed by select() on ref.current when present and of type object, ensuring the caret/selection state matches the keyboard shortcut flow.
6-6:navigator.platformis deprecated but acceptable here.For keyboard hint display (
⌘FvsCtrl F), this is a minor visual feature where the deprecated API is still widely supported. Consider usingnavigator.userAgentData?.platformwith a fallback if broader future-proofing is desired, but this is not blocking.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/renderer/components/SettingsSearchInput.tsx` at line 6, The code uses deprecated navigator.platform to set isMac which may break in future; update the isMac detection in SettingsSearchInput by first checking navigator.userAgentData?.platform (if available) and falling back to the existing typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.platform) approach; update the declaration for isMac (and any places referencing it) to use the new userAgentData-first strategy so keyboard hints (e.g., "⌘F" vs "Ctrl F") continue to render correctly.src/renderer/hooks/useSettingsSearch.ts (1)
1-14: TypetabIdasSettingsPageTabfor compile-time safety.Currently
tabId: stringallows any string value, but valid values are constrained to theSettingsPageTabunion. This forces type casts inSettingsSearchResults.tsxwhen passingtabIdtoonResultClick.♻️ Suggested fix
+import type { SettingsPageTab } from '@/components/SettingsPage'; + export interface SearchableSetting { id: string; label: string; description: string; aliases: string[]; - tabId: string; + tabId: SettingsPageTab; /** DOM element id to scroll to when this result is selected. */ elementId: string; }This also requires updating
groupResultsByTabreturn type:-export function groupResultsByTab(results: SearchResult[]): Map<string, SearchResult[]> { - const grouped = new Map<string, SearchResult[]>(); +export function groupResultsByTab(results: SearchResult[]): Map<SettingsPageTab, SearchResult[]> { + const grouped = new Map<SettingsPageTab, SearchResult[]>();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/renderer/hooks/useSettingsSearch.ts` around lines 1 - 14, Change SearchableSetting.tabId from string to the SettingsPageTab union and update any dependent types: update the SearchableSetting interface's tabId to SettingsPageTab, adjust SearchResult if necessary, and change the return type of groupResultsByTab to use SettingsPageTab keys; then update call sites (e.g. where SearchableSetting.tabId is passed to onResultClick in SettingsSearchResults.tsx) to remove casts. Ensure you import SettingsPageTab where these types are declared/used and update any type annotations referencing groupResultsByTab accordingly.src/renderer/components/SettingsSearchResults.tsx (1)
87-94: Consider aligningtabIdtype at the source to avoid casts.The
as SettingsPageTabcasts here are necessary becauseSearchableSetting.tabIdis typed asstring(seeuseSettingsSearch.tsline 6). This works but pushes type safety to runtime.A cleaner approach would be to type
tabIdasSettingsPageTabin theSearchableSettinginterface, which would provide compile-time guarantees that only valid tab IDs are used inSETTINGS_INDEX.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/renderer/components/SettingsSearchResults.tsx` around lines 87 - 94, The SearchableSetting.tabId is currently typed as string causing casts; change the SearchableSetting interface so tabId is typed as SettingsPageTab (update the interface in useSettingsSearch.ts and any other declaration) and then update all places that construct SearchableSetting (e.g., where SETTINGS_INDEX is built) to use valid SettingsPageTab values so the compiler enforces correct tab IDs and you can remove the runtime casts of tabId in SettingsSearchResults.tsx (references: SearchableSetting, useSettingsSearch.ts, tabId, SettingsPageTab, SETTINGS_INDEX).
🤖 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/renderer/components/integrations/registry.ts`:
- Around line 15-25: The explicit type annotation on INTEGRATION_REGISTRY widens
the literal types to string; remove the "readonly IntegrationRegistryEntry[]"
annotation and instead keep the array as const and use the TypeScript
"satisfies" operator to validate shape (e.g. make INTEGRATION_REGISTRY a const
array with "as const" and add "satisfies readonly IntegrationRegistryEntry[]")
so IntegrationId (defined as (typeof INTEGRATION_REGISTRY)[number]['id'])
preserves the literal union; update the declaration of INTEGRATION_REGISTRY and
leave IntegrationId unchanged.
In `@src/renderer/terminal/TerminalInputBuffer.ts`:
- Around line 46-66: processInputCharacter currently ignores the line-kill
control (Ctrl+U, '\x15'), causing a cleared line to still be captured later;
update processInputCharacter to handle '\x15' by clearing this.buffer and also
clearing/resetting this.pendingMessage (mirroring the behavior in
submitCapture.ts) so that a Ctrl+U truly discards the current input and cannot
be accidentally captured as the next message.
In `@src/renderer/terminal/writeDrainScheduler.ts`:
- Around line 24-28: The execute() function needs a one-shot completion guard to
avoid calling run() twice when both schedulers trigger; add a local or outer
boolean (e.g., "hasRun" or "isCompleted") checked at the top of execute()
(alongside isCancelled) and set to true immediately after cleanup() but before
calling run(), so subsequent execute() invocations return early; apply the same
guard to the other execute() instance referenced in the file to ensure single
execution.
- Around line 31-35: The current RAF scheduling only checks
requestAnimationFrame but cleanup() assumes cancelAnimationFrame exists; update
the guard used when setting frameId (the canUseAnimationFrame check used before
calling requestAnimationFrame in writeDrainScheduler) to require both typeof
requestAnimationFrame === 'function' and typeof cancelAnimationFrame ===
'function', and in cleanup() only call cancelAnimationFrame(frameId) when that
same combined guard is true and frameId is non-null; leave the fallback timeout
(timeoutId, VISIBLE_DRAIN_FALLBACK_MS) and execute function logic unchanged.
---
Nitpick comments:
In `@src/renderer/components/SettingsSearchInput.tsx`:
- Around line 15-20: handleClear currently calls onQueryChange('') and then
ref.current?.focus() which leaves the input unselected; change it to also call
ref.current?.select() after focus so clearing mirrors the Cmd/Ctrl+F behavior in
SettingsPage. Update the handleClear function (and any related refs used for the
input) to call focus() followed by select() on ref.current when present and of
type object, ensuring the caret/selection state matches the keyboard shortcut
flow.
- Line 6: The code uses deprecated navigator.platform to set isMac which may
break in future; update the isMac detection in SettingsSearchInput by first
checking navigator.userAgentData?.platform (if available) and falling back to
the existing typeof navigator !== 'undefined' &&
/mac|iphone|ipad|ipod/i.test(navigator.platform) approach; update the
declaration for isMac (and any places referencing it) to use the new
userAgentData-first strategy so keyboard hints (e.g., "⌘F" vs "Ctrl F") continue
to render correctly.
In `@src/renderer/components/SettingsSearchResults.tsx`:
- Around line 87-94: The SearchableSetting.tabId is currently typed as string
causing casts; change the SearchableSetting interface so tabId is typed as
SettingsPageTab (update the interface in useSettingsSearch.ts and any other
declaration) and then update all places that construct SearchableSetting (e.g.,
where SETTINGS_INDEX is built) to use valid SettingsPageTab values so the
compiler enforces correct tab IDs and you can remove the runtime casts of tabId
in SettingsSearchResults.tsx (references: SearchableSetting,
useSettingsSearch.ts, tabId, SettingsPageTab, SETTINGS_INDEX).
In `@src/renderer/hooks/useSettingsSearch.ts`:
- Around line 1-14: Change SearchableSetting.tabId from string to the
SettingsPageTab union and update any dependent types: update the
SearchableSetting interface's tabId to SettingsPageTab, adjust SearchResult if
necessary, and change the return type of groupResultsByTab to use
SettingsPageTab keys; then update call sites (e.g. where SearchableSetting.tabId
is passed to onResultClick in SettingsSearchResults.tsx) to remove casts. Ensure
you import SettingsPageTab where these types are declared/used and update any
type annotations referencing groupResultsByTab accordingly.
🪄 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: b9954af4-ea94-4953-bbc6-1c88fef35697
📒 Files selected for processing (26)
src/main/utils/gitStatusParser.tssrc/renderer/components/BrowserPreviewSettingsCard.tsxsrc/renderer/components/DefaultAgentSettingsCard.tsxsrc/renderer/components/HiddenToolsSettingsCard.tsxsrc/renderer/components/IntegrationsCard.tsxsrc/renderer/components/KeyboardSettingsCard.tsxsrc/renderer/components/NotificationSettingsCard.tsxsrc/renderer/components/RepositorySettingsCard.tsxsrc/renderer/components/ResourceMonitorSettingsCard.tsxsrc/renderer/components/ReviewAgentSettingsCard.tsxsrc/renderer/components/RightSidebarSettingsCard.tsxsrc/renderer/components/SettingsPage.tsxsrc/renderer/components/SettingsSearchInput.tsxsrc/renderer/components/SettingsSearchResults.tsxsrc/renderer/components/TaskHoverActionCard.tsxsrc/renderer/components/TaskSettingsRows.tsxsrc/renderer/components/TelemetryCard.tsxsrc/renderer/components/TerminalSettingsCard.tsxsrc/renderer/components/ThemeCard.tsxsrc/renderer/components/WorkspaceProviderInfoCard.tsxsrc/renderer/components/integrations/registry.tssrc/renderer/hooks/useSettingsSearch.tssrc/renderer/terminal/TerminalInputBuffer.tssrc/renderer/terminal/submitCapture.tssrc/renderer/terminal/writeDrainScheduler.tssrc/test/renderer/settingsSearchIndex.test.ts
- registry: use 'as const satisfies' to preserve IntegrationId literal union - TerminalInputBuffer: handle Ctrl+U (\x15) to clear buffer and pendingMessage - writeDrainScheduler: add one-shot hasRun guard; require cancelAnimationFrame - SettingsSearchInput: also select() input on clear for consistency with Cmd+F - useSettingsSearch: type tabId as SettingsPageTab; drop runtime casts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/renderer/hooks/useSettingsSearch.ts`:
- Around line 1-385: The file fails Prettier formatting—run your project's
Prettier formatter (e.g., npm run format or npx prettier --write) on the file
containing SETTINGS_INDEX, scoreField, searchSettings, and groupResultsByTab,
reformat the file to match the repo's Prettier config, verify CI/local
pre-commit hooks are happy, and commit the resulting formatted changes.
🪄 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: 40b6f2bf-2282-44e4-a55f-3e73cbf04dd9
📒 Files selected for processing (6)
src/renderer/components/SettingsSearchInput.tsxsrc/renderer/components/SettingsSearchResults.tsxsrc/renderer/components/integrations/registry.tssrc/renderer/hooks/useSettingsSearch.tssrc/renderer/terminal/TerminalInputBuffer.tssrc/renderer/terminal/writeDrainScheduler.ts
✅ Files skipped from review due to trivial changes (3)
- src/renderer/terminal/TerminalInputBuffer.ts
- src/renderer/components/integrations/registry.ts
- src/renderer/terminal/writeDrainScheduler.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/renderer/components/SettingsSearchInput.tsx
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/renderer/hooks/useSettingsSearch.ts (1)
112-144: Consider aligning section comment with actual tab identifier.The comment says "Agents Tab" but
tabIdis'clis-models'. While the UI may display "Agents", the identifier mismatch could confuse future maintainers. Consider updating to// Agents (clis-models) Tabfor clarity.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/renderer/hooks/useSettingsSearch.ts` around lines 112 - 144, The section comment "// Agents Tab" is misleading because the entries use tabId 'clis-models'; update the comment to include the actual tab identifier (for example "// Agents (clis-models) Tab") so it matches the tabId used by items like default-agent, review-agent, review-prompt, and cli-agents; ensure the updated comment appears immediately above the block that contains those objects.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/renderer/hooks/useSettingsSearch.ts`:
- Around line 112-144: The section comment "// Agents Tab" is misleading because
the entries use tabId 'clis-models'; update the comment to include the actual
tab identifier (for example "// Agents (clis-models) Tab") so it matches the
tabId used by items like default-agent, review-agent, review-prompt, and
cli-agents; ensure the updated comment appears immediately above the block that
contains those objects.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ef1a9fa2-2a28-4264-81af-43dfdadc8d78
📒 Files selected for processing (1)
src/renderer/hooks/useSettingsSearch.ts
|
Really like that addition! especially the command+f shortcut! @janburzinski |
|
typecheck should pass now :D |
Summary
finally able to search for the setting i was looking for quicker lol
very open on the design btw but its ok for testing this out for now
maybe we should make this just a search icon and when you click on it it expands(???) but then again i thought that would be too hard to maybe notice idk lol
this in general could also be a lil overcomplicated maybe but i really wanted to be able to search for e.g. jira or ticket and find jira and stuff
Fixes
#1682
Snapshot
Screen.Recording.2026-04-07.at.10.57.33.mov
Type of change
Mandatory Tasks
Checklist
Summary by CodeRabbit
New Features
New UI Components
Enhancements
Tests