Add keyboard shortcuts for jumping to sidebar threads#1456
Add keyboard shortcuts for jumping to sidebar threads#1456juliusmarminge merged 6 commits intomainfrom
Conversation
- Map the first nine visible threads to number keys - Show platform-specific shortcut hints while modifier is held - Add tests for key mapping and modifier detection
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
apps/web/src/components/Sidebar.logic.test.ts (1)
110-147: Good platform-aware modifier detection tests.Tests correctly cover:
- macOS with
metaKey- Windows with
ctrlKey- Rejection when
shiftKeyis also pressedConsider adding a test case for
altKey: trueto verify it's also rejected, matching the implementation requirement.📝 Optional: Add altKey rejection test
expect( isThreadJumpModifierPressed( { key: "Control", metaKey: false, ctrlKey: true, shiftKey: false, altKey: true, }, "Win32", ), ).toBe(false);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/components/Sidebar.logic.test.ts` around lines 110 - 147, Add a test asserting that isThreadJumpModifierPressed rejects when altKey is true: in the test "detects the active jump modifier by platform" add a case calling isThreadJumpModifierPressed with a Windows platform ("Win32") and an event object where ctrlKey: true, altKey: true (and shiftKey: false, metaKey: false) and expect the result to be false; this mirrors the existing shiftKey rejection case and verifies altKey is also treated as an invalid modifier.apps/web/src/components/Sidebar.logic.ts (1)
81-111: Defaultnavigator.platformmay throw in non-browser contexts.While Sidebar.tsx always passes
platformexplicitly, the default parameternavigator.platformwould throw aReferenceErrorif these helpers are ever called without an argument in SSR or test environments wherenavigatoris undefined.Consider using a safer default or documenting that the argument is required outside browser contexts.
🛡️ Suggested defensive default
export function isThreadJumpModifierPressed( event: ThreadJumpEvent, - platform = navigator.platform, + platform = typeof navigator !== "undefined" ? navigator.platform : "", ): boolean {Apply the same pattern to
resolveThreadJumpIndexandformatThreadJumpHintLabel.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/components/Sidebar.logic.ts` around lines 81 - 111, Defaulting parameters to navigator.platform can throw in non-browser environments; update isThreadJumpModifierPressed, resolveThreadJumpIndex, and formatThreadJumpHintLabel to use a safe platform default (e.g. const safePlatform = typeof navigator !== "undefined" ? navigator.platform : "" or undefined) instead of directly using navigator.platform in the parameter list, then use safePlatform in calls to isMacPlatform and other logic so these helpers won’t ReferenceError in SSR/tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/web/src/components/Sidebar.logic.test.ts`:
- Around line 110-147: Add a test asserting that isThreadJumpModifierPressed
rejects when altKey is true: in the test "detects the active jump modifier by
platform" add a case calling isThreadJumpModifierPressed with a Windows platform
("Win32") and an event object where ctrlKey: true, altKey: true (and shiftKey:
false, metaKey: false) and expect the result to be false; this mirrors the
existing shiftKey rejection case and verifies altKey is also treated as an
invalid modifier.
In `@apps/web/src/components/Sidebar.logic.ts`:
- Around line 81-111: Defaulting parameters to navigator.platform can throw in
non-browser environments; update isThreadJumpModifierPressed,
resolveThreadJumpIndex, and formatThreadJumpHintLabel to use a safe platform
default (e.g. const safePlatform = typeof navigator !== "undefined" ?
navigator.platform : "" or undefined) instead of directly using
navigator.platform in the parameter list, then use safePlatform in calls to
isMacPlatform and other logic so these helpers won’t ReferenceError in
SSR/tests.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f3c49538-55ac-433c-86b5-46df99b9e76a
📒 Files selected for processing (3)
apps/web/src/components/Sidebar.logic.test.tsapps/web/src/components/Sidebar.logic.tsapps/web/src/components/Sidebar.tsx
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| }); | ||
| }, | ||
| [clearSelection, navigate, selectedThreadIds.size, setSelectionAnchor], | ||
| ); |
There was a problem hiding this comment.
Duplicated navigation logic in handleThreadClick and navigateToThread
Low Severity
The new navigateToThread callback duplicates the plain-click branch of the existing handleThreadClick callback (clear selection, set anchor, navigate). The plain-click path in handleThreadClick (lines 964–972) performs the exact same sequence — check selectedThreadIds.size, call clearSelection, setSelectionAnchor, and navigate — but was not updated to call navigateToThread. This duplication means a future change to the navigation logic risks being applied in one place but missed in the other.
Additional Locations (1)
- add archive/unarchive commands, projections, and persistence - surface archived-thread state in the UI and settings - improve bootstrap, editor launch, and shell env handling
- Add thread previous/next and jump-by-number bindings - Update sidebar navigation and hint rendering to use them - Expand keybinding and contract tests for thread shortcuts
6aadae6 to
9c8e8c6
Compare
…shortcuts # Conflicts: # apps/web/src/components/Sidebar.logic.test.ts # apps/web/src/components/Sidebar.logic.ts # apps/web/src/components/Sidebar.tsx
- Treat shadowed keybindings as unavailable when rendering labels - Pass terminal/thread context into chat and sidebar shortcut lookups - Update tests for effective binding resolution and when-clause matching
- Bind fork/promise helpers to the current services in Claude adapter and tests - Switch drainable worker to tx primitives and simplify enqueue - Classify sqlite errors with the built-in helper - Update tests to use the new Effect mocking and runtime helpers
Upstream changes (v0.0.15): - Refactor projection pipeline side effects (pingdotgg#1512) - Inline sqlite error classification (pingdotgg#1515) - DrainableWorker drain off outstanding count (pingdotgg#1514) - Thread archiving with archivedAt (pingdotgg#1505-related migrations) - Auto-generate first-turn thread titles (pingdotgg#1375) - Keyboard shortcuts for sidebar threads (pingdotgg#1456) - Various UI fixes (sidebar, settings, markdown links) Conflict resolution: - ProjectionPipeline.ts: took upstream (our REINDEX workaround no longer needed with doltlite canDefer=0 fix) - Migrations.ts: renumbered our 016-018 to 019-021, keeping upstream's 016-018 (CanonicalizeModelSelections, ArchivedAt) - ProjectionThreads.ts, orchestration.ts: took upstream (archiving) - Sidebar files: took upstream (new features) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>


Summary
Cmd+1-Cmd+9on macOS,Ctrl+1-Ctrl+9elsewhere).Mod+Shift+[andMod+Shift+]for back/forwardTesting
Not runNote
Medium Risk
Adds new global
windowkeyboard listeners and expands the supported keybinding command set, which could introduce shortcut conflicts or unexpected navigation if matching logic is wrong.Overview
Adds default keybindings and contract support for
thread.jump.1throughthread.jump.9, enabling Cmd/Ctrl+number shortcuts.Implements sidebar thread-jump navigation: computes the first 9 visible thread targets, intercepts matching shortcut events to navigate (reusing the existing selection/anchor behavior), and shows inline shortcut hint badges while the modifier key is held. Includes unit tests for jump target selection and command index parsing.
Written by Cursor Bugbot for commit 6aadae6. This will update automatically on new commits. Configure here.
Note
Add keyboard shortcuts for jumping to sidebar threads
thread.previous(mod+shift+[),thread.next(mod+shift+]), and numeric jump shortcuts (mod+1–mod+9) for navigating between sidebar threads.event.code(physical key) in addition toevent.key, improving reliability across keyboard layouts for bracket and digit shortcuts.shortcutLabelForCommandnow accepts when-context and platform options, resolving the effective label accounting for conflicts and conditional bindings.threadJumpCommandForIndex,resolveAdjacentThreadId,getVisibleSidebarThreadIds) are added to support index-based and previous/next thread traversal logic.Macroscope summarized 954546f.
Summary by CodeRabbit