Skip to content

feat(settings): context-aware Cmd+K settings search (from #349) - #399

Merged
ruzin merged 2 commits into
mainfrom
feat/settings-cmdk-search
Jul 23, 2026
Merged

feat(settings): context-aware Cmd+K settings search (from #349)#399
ruzin merged 2 commits into
mainfrom
feat/settings-cmdk-search

Conversation

@ruzin

@ruzin ruzin commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds context-aware Cmd+K to Settings: while the Settings page is open, the global command palette switches to "Search settings…" mode — it filters an index of the app's settings (theme, microphone, AI provider, export, …) and jumps to the tab each one lives on, instead of searching notes.

This is the settings-search piece of @Vassista's #349, extracted and adapted to the current nav-rail Settings design so it does not change how Settings looks.

What changed

  • CommandPalette.tsx — when the route is /settings, the palette searches a SETTINGS_INDEX and navigates to /settings?tab=<id>. Placeholder/aria/empty-state all switch to settings mode; note search is unchanged elsewhere. The index is retargeted to the current tabs (transcription settings live on the AI tab now; added an About entry) — the original PR's index used the pre-v0.6.2 tab layout.
  • Settings.tsx — the visible tab now re-derives from the ?tab= param after mount (previously mount-only), so selecting a result switches tabs even when Settings is already open. Purely behavioral — no layout/visual change.

Why not just merge #349

#349 is 17 commits stale and its centrepiece is a Settings-UI refactor that predates (and would undo) the v0.6.2 nav-rail redesign. This PR takes only the search, rebuilt on the current design. Cloud transcription, notification, and other pieces of #349 are being extracted as separate PRs.

Tests

  • New T1 settings-cmdk-search.t1.spec.ts: settings-mode search + filtering, and the route-reactive tab switch (jump from the AI tab to a General-tab setting). Existing notes-search palette specs still pass.
  • typecheck:renderer green.

Credit: @Vassista (#349).


Summary by cubic

Adds context-aware Cmd+K to Settings: while on /settings, the palette switches to “Search settings…” and jumps to the right tab. Note search stays the same elsewhere.

  • New Features
    • Cmd+K detects /settings, filters a settings index, and opens /settings?tab=… for the selected item; placeholder/aria/empty-state switch to settings mode. Note search is unchanged on other routes.
    • Settings now reacts to ?tab= changes after mount so selections switch tabs even when Settings is already open; adds a T1 spec covering settings-mode search, query trimming, and tab switching.
    • Polish from review: trim queries, guard aria-activedescendant when the list shrinks, match real labels (e.g., “Post meeting notifications”), and expand the index (Scheduled meetings, Storage location, dock icon); reset the Templates editor flag when leaving that tab.

Written for commit dd2faaf. Summary will update on new commits.

Review in cubic

While the Settings page is open, the global Cmd+K palette switches to
"Search settings…" mode: it filters an index of the app's settings and
navigates to the tab each one lives on, instead of searching notes.

Ported from @Vassista's PR #349 and adapted to the current nav-rail
Settings design — the search index is retargeted to the current tab ids
(transcription settings map to the AI tab; adds About), and Settings.tsx
now re-derives its visible tab from the route param after mount so a
selection switches tabs even when Settings is already open. Does not
touch the Settings layout/look.

Adds a T1 spec covering settings-mode search + the route-reactive tab switch.

Co-authored-by: Vassista <vassista@icloud.com>
@ruzin
ruzin requested a review from Optic00 as a code owner July 23, 2026 18:10

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 3 files

You’re at about 90% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/renderer/src/routes/Settings.tsx">

<violation number="1" location="app/renderer/src/routes/Settings.tsx:93">
P2: Changing the hash from a valid deep link such as `/settings?tab=ai` to `/settings` (or to an invalid tab) leaves the old tab visible because this effect has no fallback branch. The route-sync logic should also reset `tab` to `'general'` when `requested` is absent or invalid, matching the mount behavior.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread app/renderer/src/routes/Settings.tsx
Comment on lines +93 to +95
if (requested && (DEEP_LINK_IDS as readonly string[]).includes(requested)) {
setTab(resolveTab(requested as DeepLinkId));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Changing the hash from a valid deep link such as /settings?tab=ai to /settings (or to an invalid tab) leaves the old tab visible because this effect has no fallback branch. The route-sync logic should also reset tab to 'general' when requested is absent or invalid, matching the mount behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/renderer/src/routes/Settings.tsx, line 93:

<comment>Changing the hash from a valid deep link such as `/settings?tab=ai` to `/settings` (or to an invalid tab) leaves the old tab visible because this effect has no fallback branch. The route-sync logic should also reset `tab` to `'general'` when `requested` is absent or invalid, matching the mount behavior.</comment>

<file context>
@@ -84,6 +84,16 @@ export function Settings() {
+  // so without this the hash would update but the tab wouldn't switch.
+  React.useEffect(() => {
+    const requested = getRouteParam(route, 'tab');
+    if (requested && (DEEP_LINK_IDS as readonly string[]).includes(requested)) {
+      setTab(resolveTab(requested as DeepLinkId));
+    }
</file context>
Suggested change
if (requested && (DEEP_LINK_IDS as readonly string[]).includes(requested)) {
setTab(resolveTab(requested as DeepLinkId));
}
if (requested && (DEEP_LINK_IDS as readonly string[]).includes(requested)) {
setTab(resolveTab(requested as DeepLinkId));
} else {
setTab('general');
}

Comment thread app/renderer/src/components/CommandPalette.tsx
Comment thread app/renderer/src/components/CommandPalette.tsx Outdated
Comment thread app/renderer/src/components/CommandPalette.tsx Outdated
Comment thread app/renderer/src/components/CommandPalette.tsx Outdated
- Match the real label 'Post meeting notifications' (no hyphen) so the
  displayed setting is findable (cubic P3, conf 10).
- Trim the query before filtering settings so leading/trailing whitespace
  still matches (cubic P3, conf 10).
- Guard aria-activedescendant against a transiently out-of-range selection
  after the list shrinks (cubic P3).
- Add Storage location + Scheduled meetings to the index and surface the
  menu-bar/tray icon setting, so more visible settings are discoverable
  (cubic P2).
- Reset templateEditorOpen when leaving the Templates tab (via nav or
  search) so a stale flag can't suppress the page header (cubic P2).
- Extend the T1 spec to cover the trim + real-label match.
@ruzin

ruzin commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the cubic review in dd2faaf:

  • P3 (conf 10) — "Post meeting notifications" not findable: index title had a hyphen the real label doesn't; matched it exactly. ✅
  • P3 (conf 10) — whitespace query returns nothing: now trim before lowercasing/filtering. ✅
  • P3 — aria-activedescendant can reference a nonexistent option: restored a guard so it's only set when an option exists at selected. ✅
  • P2 — undiscoverable settings: added Storage location and Scheduled meetings, and surfaced the menu-bar/tray setting in the dock entry's subtitle. ✅
  • P2 — stale templateEditorOpen: reset it whenever the active tab isn't Templates (covers both the nav rail and the ⌘K search path). ✅

Not changing — P2 (Settings.tsx: navigating to /settings or an invalid tab leaves the old tab visible): this isn't a regression. Before this PR the tab was consumed on mount only, so no post-mount hash change switched tabs at all; the new effect strictly improves that by switching on any valid ?tab=. The settings search always navigates to a valid ?tab=, so the flagged path isn't reachable through the feature. Deliberately preserving the current tab on a param-less /settings avoids clobbering the tab on unrelated internal navigations that land on /settings without a param. Extended the T1 spec to cover the trim + real-label cases.

@ruzin
ruzin merged commit fcf3248 into main Jul 23, 2026
10 checks passed
@ruzin
ruzin deleted the feat/settings-cmdk-search branch July 23, 2026 19:06
@Optic00

Optic00 commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Same timing story as #401: review finalised as it merged. One interaction bug worth a follow-up landed in #405 - after a manual tab switch, a repeated ⌘K settings search can silently no-op because tab state and URL diverge. Repro + fix directions in the issue.

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.

2 participants