Skip to content

feat(sidebar): add chat number shortcuts#1730

Merged
zerob13 merged 3 commits into
devfrom
feat/switch-channels
Jun 3, 2026
Merged

feat(sidebar): add chat number shortcuts#1730
zerob13 merged 3 commits into
devfrom
feat/switch-channels

Conversation

@zerob13
Copy link
Copy Markdown
Collaborator

@zerob13 zerob13 commented Jun 3, 2026

Summary

  • add Cmd/Alt + number shortcuts for switching the first ten visible sidebar chats
  • show shortcut badges after a 0.5s platform-modifier hold without coupling to hover state
  • add localized shortcut tooltip text and renderer tests for mapping, focus guards, overlays, and cleanup

Tests

  • pnpm run format
  • pnpm run i18n
  • pnpm run lint
  • pnpm run typecheck
  • pnpm exec vitest --config vitest.config.renderer.ts test/renderer/components/WindowSideBar.test.ts test/renderer/components/WindowSideBarSessionItem.test.ts

UI Structure

Before:

+--------------------------------------+
| Chat title                      [del]|
+--------------------------------------+

After holding Cmd/Alt for 0.5s:

+--------------------------------------+
| Chat title                       [⌘1]|
| Next chat                         [⌘2]|
+--------------------------------------+

Summary by CodeRabbit

  • New Features
    • Added keyboard shortcuts to quickly switch between sidebar chats using platform-specific modifiers (⌘ on macOS, Alt on Windows/Linux) with number keys 1–9 and 0 for the 10th chat
    • Added visual shortcut badges on sidebar items indicating available keyboard shortcuts
    • Updated translations across 18 languages to support the new feature

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e53b4ca-ccd8-4de6-80c2-0c9ea6a73c25

📥 Commits

Reviewing files that changed from the base of the PR and between dfc2179 and 5401fb8.

📒 Files selected for processing (3)
  • src/renderer/src/components/WindowSideBar.vue
  • test/renderer/components/WindowSideBar.test.ts
  • test/renderer/components/WindowSideBarSessionItem.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/renderer/components/WindowSideBarSessionItem.test.ts
  • test/renderer/components/WindowSideBar.test.ts
  • src/renderer/src/components/WindowSideBar.vue

📝 Walkthrough

Walkthrough

This PR implements numbered keyboard shortcuts (1–9, 0) for sidebar chat session selection. The feature adds macOS (⌘) and Windows/Linux (Alt) modifier support with visual badge overlays, keyboard event handling, and comprehensive test coverage across 22 languages.

Changes

Sidebar Chat Number Shortcuts

Layer / File(s) Summary
Feature Specification & Planning
docs/features/sidebar-chat-number-shortcuts/*
Spec, plan, and tasks documentation define user goals, acceptance criteria, keyboard event flow, implementation scope boundaries, and validation/risk mitigation for the sidebar number shortcut feature.
Session Item Badge Props & Rendering
src/renderer/src/components/WindowSideBarSessionItem.vue
Component accepts shortcutBadgeLabel and shortcutBadgeVisible props; renders a conditional shortcut badge with localized tooltip/ARIA-label instead of the delete button; styles badge and button interactions.
Sidebar Shortcut Infrastructure & State
src/renderer/src/components/WindowSideBar.vue
Adds createDeviceClient import and constants for badge timing/max rows; creates platform-discriminated type; initializes shared device client instance; adds reactive state for modifier-held, badge timer, and show flag; implements computed derivation of visible shortcut sessions filtered by collapsed state, pinned/group visibility, and pin-flight exclusion; maps session indexes to platform-specific badge labels.
Badge Props Wiring to Session Items
src/renderer/src/components/WindowSideBar.vue
Template passes computed shortcut badge label and visibility into both pinned and grouped WindowSideBarSessionItem components.
Keyboard Event Handling & Lifecycle Wiring
src/renderer/src/components/WindowSideBar.vue
Implements modifier-only keydown detection (with platform-specific default prevention), digit-key session selection, delayed badge-show timer, multiple badge-hide paths (modifier keyup, blur, document hidden, sidebar collapse), and window/document listener registration/cleanup on mount/unmount.
i18n Translations for Shortcut Badge
src/renderer/src/i18n/*/thread.json
Adds switchWithShortcut action label with {shortcut} placeholder across 22 language files (da-DK, de-DE, en-US, es-ES, fa-IR, fr-FR, he-IL, id-ID, it-IT, ja-JP, ko-KR, ms-MY, pl-PL, pt-BR, ru-RU, tr-TR, vi-VN, zh-CN, zh-HK, zh-TW) to localize badge tooltip and ARIA text.
Test Harness & Keyboard Simulation Helpers
test/renderer/components/WindowSideBar.test.ts
Test setup adds optional platform field to SetupOptions; mocks deviceClient with configurable platform detection; tracks mounted wrappers for centralized cleanup in afterEach; exposes deviceClient from setup; provides dispatchWindowKeydown/dispatchWindowKeyup helpers for keyboard event simulation with optional modifier flags.
Shortcut Selection & Badge Lifecycle Tests
test/renderer/components/WindowSideBar.test.ts
Comprehensive Vitest suite covering macOS/Windows/Linux modifier mapping, session selection via digit keys from visible rows, suppression rules (collapsed sidebar, editable targets, spotlight overlay), shortcut repeat handling, badge long-press timing and cancellation, and listener cleanup on unmount.
Badge Rendering & Session Item Tests
test/renderer/components/WindowSideBarSessionItem.test.ts
Updates test harness to accept shortcutBadgeLabel and shortcutBadgeVisible props; adds test verifying badge renders independently of delete action (badge present with label/ARIA when visible; delete present when badge hidden).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ThinkInAIXYZ/deepchat#1542: Modifies sidebar collapsed/visibility behavior and CSS inert state, which affects the sidebar session rows that shortcut badge eligibility logic depends on.

Poem

🐰 With numbers swift, now leap through chats,
Command on Mac, Alt on the rest,
Long-press reveals the hidden path,
Twenty-two tongues sing the quest,
Keyboard shortcuts pass the test! 🎯

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(sidebar): add chat number shortcuts' clearly and concisely describes the main feature addition—keyboard number shortcuts for switching between sidebar chats.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/switch-channels

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.

@zerob13 zerob13 changed the base branch from main to dev June 3, 2026 09:05
Copy link
Copy Markdown
Contributor

@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: 2

🧹 Nitpick comments (1)
test/renderer/components/WindowSideBarSessionItem.test.ts (1)

144-169: 💤 Low value

Consider verifying the data attribute is absent when badge is hidden.

The test comprehensively verifies that the badge and delete button render exclusively. However, when the badge is not visible (lines 160-169), you could add an assertion to confirm that the data-shortcut-badge-visible attribute is not present on the .right-button element, mirroring the positive assertion at line 156-158.

✨ Optional assertion to add
   expect(normalWrapper.find('[data-testid="sidebar-session-shortcut-badge"]').exists()).toBe(
     false
   )
   expect(normalWrapper.find('[aria-label="thread.actions.delete"]').exists()).toBe(true)
+  expect(normalWrapper.find('.right-button').attributes('data-shortcut-badge-visible')).toBeUndefined()
 }, 10000)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/renderer/components/WindowSideBarSessionItem.test.ts` around lines 144 -
169, In the test "renders shortcut badges independently from the delete action",
add a negative assertion for the data attribute when the badge is hidden. After
creating normalWrapper via mountComponent with shortcutBadgeVisible: false,
verify that normalWrapper.find('.right-button') does not have the
data-shortcut-badge-visible attribute (mirroring the positive check done on
badgeWrapper for 'true'). Keep existing assertions for the absence of the badge
and presence of the delete button intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/renderer/src/components/WindowSideBar.vue`:
- Around line 942-952: The isSidebarShortcutDigitEvent predicate is treating
auto-repeated keydown events as new shortcut invocations; add a guard that
ignores auto-repeat events (KeyboardEvent.repeat) so the shortcut only fires on
the initial keydown. Update the isSidebarShortcutDigitEvent function to return
false when event.repeat is true before checking modifiers and digit, keeping the
existing platform-specific modifier checks (shortcutPlatform.value === 'mac'
branch and the altKey branch) intact.

In `@test/renderer/components/WindowSideBar.test.ts`:
- Around line 553-926: Tests that dispatch real window keyboard events leave
WindowSideBar listeners registered, causing order-dependent failures; ensure
mounted wrappers are unmounted between tests by tearing down components returned
from setup. Update tests that use dispatchWindowKeydown or the WindowSideBar
behavior (references: setup(), WindowSideBar, dispatchWindowKeydown, wrapper) to
call wrapper.unmount() after use or add a global afterEach that tracks and
unmounts the wrapper returned by setup (or modify setup to register a
cleanup/unmount for the test harness). This guarantees window shortcut listeners
are removed before the next spec runs.

---

Nitpick comments:
In `@test/renderer/components/WindowSideBarSessionItem.test.ts`:
- Around line 144-169: In the test "renders shortcut badges independently from
the delete action", add a negative assertion for the data attribute when the
badge is hidden. After creating normalWrapper via mountComponent with
shortcutBadgeVisible: false, verify that normalWrapper.find('.right-button')
does not have the data-shortcut-badge-visible attribute (mirroring the positive
check done on badgeWrapper for 'true'). Keep existing assertions for the absence
of the badge and presence of the delete button intact.
🪄 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: 9b184446-baec-4b95-ab60-8c6129cd6947

📥 Commits

Reviewing files that changed from the base of the PR and between 0422b97 and dfc2179.

📒 Files selected for processing (27)
  • docs/features/sidebar-chat-number-shortcuts/plan.md
  • docs/features/sidebar-chat-number-shortcuts/spec.md
  • docs/features/sidebar-chat-number-shortcuts/tasks.md
  • src/renderer/src/components/WindowSideBar.vue
  • src/renderer/src/components/WindowSideBarSessionItem.vue
  • src/renderer/src/i18n/da-DK/thread.json
  • src/renderer/src/i18n/de-DE/thread.json
  • src/renderer/src/i18n/en-US/thread.json
  • src/renderer/src/i18n/es-ES/thread.json
  • src/renderer/src/i18n/fa-IR/thread.json
  • src/renderer/src/i18n/fr-FR/thread.json
  • src/renderer/src/i18n/he-IL/thread.json
  • src/renderer/src/i18n/id-ID/thread.json
  • src/renderer/src/i18n/it-IT/thread.json
  • src/renderer/src/i18n/ja-JP/thread.json
  • src/renderer/src/i18n/ko-KR/thread.json
  • src/renderer/src/i18n/ms-MY/thread.json
  • src/renderer/src/i18n/pl-PL/thread.json
  • src/renderer/src/i18n/pt-BR/thread.json
  • src/renderer/src/i18n/ru-RU/thread.json
  • src/renderer/src/i18n/tr-TR/thread.json
  • src/renderer/src/i18n/vi-VN/thread.json
  • src/renderer/src/i18n/zh-CN/thread.json
  • src/renderer/src/i18n/zh-HK/thread.json
  • src/renderer/src/i18n/zh-TW/thread.json
  • test/renderer/components/WindowSideBar.test.ts
  • test/renderer/components/WindowSideBarSessionItem.test.ts

Comment thread src/renderer/src/components/WindowSideBar.vue
Comment thread test/renderer/components/WindowSideBar.test.ts
@zerob13 zerob13 merged commit 9d5f0db into dev Jun 3, 2026
3 checks passed
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