Skip to content

feat: add global keyboard shortcut system (closes #83)#119

Merged
krishkhinchi merged 1 commit into
7-Blocks:mainfrom
SankeerthNara:Add-Global-Keyboard-Shortcuts
Jul 22, 2026
Merged

feat: add global keyboard shortcut system (closes #83)#119
krishkhinchi merged 1 commit into
7-Blocks:mainfrom
SankeerthNara:Add-Global-Keyboard-Shortcuts

Conversation

@SankeerthNara

@SankeerthNara SankeerthNara commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

User description

Description

Implements a centralized global keyboard shortcut system for Kepler, per issue #83.

  • utils/keyboardShortcuts.ts — single source of truth for every shortcut in the app: navigation, search, data actions, table navigation, globe controls, dashboard controls, and utility shortcuts. Adding a new shortcut means adding one entry here.
  • hooks/useKeyboardShortcuts.ts — one window keydown listener (no scattered per-component handlers). Ignores typing contexts (inputs, textareas, contenteditable, and rich editors like Monaco/CodeMirror/ProseMirror), resolves Ctrl/Shift/Alt combos (mapping CmdCtrl on macOS), and manages the help modal's open/close state internally so ? and Ctrl+/ work with zero extra wiring.
  • components/ShortcutHelpModal.tsx — categorized cheat sheet styled with Kepler's existing design tokens (bg-surface-container, border-border-panel, font-technical-data, MaterialIcon), responsive, closes on Esc or backdrop click.
  • App.tsx — wires it all together: navigation shortcuts route to the real dashboard pages, Ctrl+D toggles the sidebar via the existing uiStore, and Ctrl+R / Ctrl+Shift+R invalidate React Query's cache for a generic refresh.

Known gap: Telemetry, Space Weather, Risk Assessment, and Prediction Analytics don't have dedicated pages yet, so those four navigation shortcuts are defined and visible in the help modal (per the issue's spec) but intentionally left unwired — pressing them is a safe no-op rather than a 404. They'll just need a handler added in App.tsx once those routes exist.

Related Issue

Closes #83

Checklist

  • I have read the contributing guidelines
  • My code follows the project guidelines
  • I have completed testing of my changes
  • Documentation has been updated (if applicable)

Screenshots / Screen Recordings

image

Testing Notes

Manually verified:

  • ? / Ctrl+/ open the help modal; Esc and backdrop click close it
  • S, C, A, M navigate to Satellites, Collision Center, AI Agents, and Mission Planner respectively
  • Typing in the ID/TLE search bar (and other inputs) does not trigger navigation shortcuts
  • Ctrl+D collapses/expands the sidebar
  • No console errors during any of the above
  • pnpm build passes clean on these changes (two pre-existing, unrelated type errors in ProductPage.tsx/DevelopersPage.tsx remain on main and aren't touched by this PR)

Breaking Changes

None.


CodeAnt-AI Description

Add global keyboard shortcuts and an in-app shortcut guide

What Changed

  • Added global shortcuts for navigation, search, refresh, sidebar control, and help, so common actions can be triggered from anywhere in the app.
  • Added a shortcut help modal that shows all available shortcuts, grouped by use case, and can be closed with Esc or by clicking outside it.
  • Shortcuts now avoid text entry areas, so typing in forms and editors is not interrupted.
  • Some shortcuts are shown in the help guide before their pages exist; those entries do nothing for now instead of sending users to broken pages.

Impact

✅ Faster navigation across the dashboard
✅ Quicker access to search and refresh
✅ Fewer accidental shortcut triggers while typing

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features
    • Added app-wide keyboard shortcuts for navigation, global search, data refresh, and sidebar toggling.
    • Added a shortcut help modal with platform-specific key labels and categorized shortcut descriptions.
    • Shortcuts now respect typing contexts and support Mac and non-Mac key combinations.
    • Added focus management and animated transitions when opening or closing the shortcut help modal.

Greptile Summary

This PR adds a centralized global keyboard shortcut system. The main changes are:

  • A shared shortcut registry for navigation, data, table, globe, dashboard, and utility actions.
  • A window-level hook for matching keys and ignoring typing contexts.
  • A categorized shortcut-help modal with platform-specific labels.
  • Global handlers for navigation, search, query refresh, and sidebar control.

Confidence Score: 4/5

Several advertised shortcuts are broken, and dashboard navigation keys run on public and authentication routes.

  • The question-mark event is rejected on common keyboard layouts.
  • Global search changes unused state and produces no visible result.
  • Unmodified dashboard keys can unexpectedly navigate away from non-dashboard pages.
  • Multiple shortcut groups are shown despite having no registered handlers.
  • Keyboard focus can leave the modal while it is open.

frontend/src/App.tsx, frontend/src/utils/keyboardShortcuts.ts, frontend/src/components/ShortcutHelpModal.tsx

Important Files Changed

Filename Overview
frontend/src/App.tsx Mounts global shortcuts across every route and wires navigation, search state, query refresh, and sidebar actions.
frontend/src/hooks/useKeyboardShortcuts.ts Adds global event matching, typing-context filtering, exact modifier checks, and help-modal state.
frontend/src/utils/keyboardShortcuts.ts Defines the shortcut registry, including several entries with no active handler and a mismatched question-mark combination.
frontend/src/components/ShortcutHelpModal.tsx Adds the animated help dialog and focus restoration, but does not contain keyboard focus.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    K[Window keydown] --> T{Typing context?}
    T -->|Yes| I[Ignore shortcut]
    T -->|No| M[Match key and modifiers]
    M --> H{Help action?}
    H -->|Yes| D[Toggle help dialog]
    H -->|No| R{Handler registered?}
    R -->|Yes| A[Run application action]
    R -->|No| N[Silent no-op]
Loading
Prompt To Fix All With AI
Fix the following 8 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 8
frontend/src/utils/keyboardShortcuts.ts:127
**Question-Mark Shortcut Never Matches**

On common layouts such as US keyboards, pressing `?` produces `key === '?'` with `shiftKey === true`. This definition requests no Shift modifier, so the exact modifier check rejects the event and the help modal does not open.

### Issue 2 of 8
frontend/src/App.tsx:52
**Global Search Has No Consumer**

Pressing Ctrl/Cmd+K prevents the browser default and sets `globalSearchOpen`, but no rendered component reads that state. The advertised shortcut therefore has no visible effect while also taking over the browser shortcut.

### Issue 3 of 8
frontend/src/App.tsx:43-49
**Dashboard Keys Leak Across Routes**

`GlobalShortcuts` is mounted outside the route layouts, so these unmodified letter shortcuts remain active on marketing and authentication pages. Pressing `S`, `G`, `D`, `C`, `A`, `M`, or `H` while no input is focused unexpectedly leaves the current public page and navigates into the dashboard.

### Issue 4 of 8
frontend/src/components/ShortcutHelpModal.tsx:27-31
**Modal Focus Escapes Backdrop**

This effect moves focus into the dialog but does not keep it there. A keyboard user can Tab past the modal controls into interactive content behind the backdrop, even though the dialog declares `aria-modal="true"`.

### Issue 5 of 8
frontend/src/utils/keyboardShortcuts.ts:90-95
**Help Lists Inactive Data Actions**

The modal renders these entries from the global registry, but `App.tsx` registers only the two refresh handlers. Ctrl+E, Ctrl+Shift+E, and Ctrl+S therefore match a definition and then silently do nothing, so the cheat sheet advertises actions that are unavailable.

### Issue 6 of 8
frontend/src/utils/keyboardShortcuts.ts:98-107
**Table Shortcuts Have No Registration Path**

Every table command is displayed in the help modal, but the only hook instance uses the global definitions and supplies none of these handlers. No page registers a scoped shortcut hook, so all ten advertised table shortcuts are reachable no-ops.

### Issue 7 of 8
frontend/src/utils/keyboardShortcuts.ts:110-116
**Globe Shortcuts Are Unwired**

These controls are shown as available in the help modal, but neither the global handler map nor the globe view registers their handler keys. Pressing the advertised zoom, camera, label, debris, orbit, or focus keys therefore produces no globe action.

### Issue 8 of 8
frontend/src/utils/keyboardShortcuts.ts:83
**Escape Only Closes Help**

The registry advertises Escape as closing an open modal or dialog, but the hook handles this key only when its own help modal is open and `App.tsx` supplies no general `closeModal` handler. Other application dialogs remain open when users invoke the advertised shortcut.

Reviews (1): Last reviewed commit: "feat: add global keyboard shortcut syste..." | Re-trigger Greptile

Greptile also left 8 inline comments on this PR.

- Centralized shortcut registry (utils/keyboardShortcuts.ts) covering all shortcuts from the issue: navigation, search, data actions, table nav, globe controls, dashboard controls, utility.
- useKeyboardShortcuts hook: single window keydown listener, ignores typing contexts (inputs/textareas/contenteditable/code editors), handles Ctrl/Shift/Alt (+ Cmd on macOS), built-in help modal toggle.
- ShortcutHelpModal: categorized cheat sheet styled with Kepler's existing design tokens, closes on Esc/backdrop click.
- Wired into App.tsx: nav shortcuts -> real dashboard routes, sidebar toggle -> uiStore, refresh -> React Query cache invalidation.
- Telemetry/Space Weather/Risk Assessment/Prediction Analytics have no pages yet, so those shortcuts are defined (visible in the help modal) but intentionally left unwired until those routes exist.

Signed-off-by: SankeerthNara <sankeerthnara@gmail.com>
@codeant-ai

codeant-ai Bot commented Jul 22, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 1406b45 Jul 22, 2026 · 05:58 06:01

Updated in place by CodeAnt AI · last 5 reviews

@github-actions github-actions Bot added AI Artificial Intelligence and Machine Learning bug Something isn't working documentation Improvements or additions to documentation frontend Frontend development size/L Large contribution requiring significant work. size:L Large size type:bug Fixes an existing bug or unexpected behavior. type:documentation Improves project documentation. type:frontend Changes frontend or client-side code. labels Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a centralized keyboard shortcut registry and global event hook, wires shortcuts to navigation and UI actions, and introduces a responsive, focus-managed help modal available across application routes.

Changes

Global keyboard shortcuts

Layer / File(s) Summary
Shortcut definitions and formatting
frontend/src/utils/keyboardShortcuts.ts
Defines typed shortcut metadata, platform-specific key formatting, category ordering, and grouping.
Global keyboard event dispatch
frontend/src/hooks/useKeyboardShortcuts.ts
Matches global key events, filters typing contexts, manages help state, and invokes mapped handlers.
Shortcut help UI and application integration
frontend/src/components/ShortcutHelpModal.tsx, frontend/src/App.tsx
Renders the animated help dialog and connects global shortcuts to navigation, search, query refresh, and sidebar actions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant GlobalShortcuts
  participant useKeyboardShortcuts
  participant AppState
  User->>useKeyboardShortcuts: Press registered shortcut
  useKeyboardShortcuts->>GlobalShortcuts: Dispatch mapped handler
  GlobalShortcuts->>AppState: Navigate, refresh queries, open search, or toggle sidebar
Loading

Possibly related issues

  • #83 — Adds the requested global shortcut manager, centralized definitions, application actions, typing-context handling, and help modal.

Suggested labels: enhancement, type:feature

Suggested reviewers: krishkhinchi

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title is concise and accurately summarizes the global keyboard shortcut system change.
Description check ✅ Passed The description is detailed and covers the required template sections, including issue link, checklist, screenshots, and breaking changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@codeant-ai codeant-ai Bot added size:L Large size and removed size:L Large size labels Jul 22, 2026
@github-actions github-actions Bot added enhancement New feature or request type:feature Introduces a new feature or enhancement. labels Jul 22, 2026

// Utility
{ id: 'util-help-slash', combo: { key: '/', modifiers: ['ctrl'] }, description: 'Open shortcut help', category: 'Utility', handlerKey: 'openShortcutHelp' },
{ id: 'util-help-question', combo: { key: '?' }, description: 'Show shortcut cheat sheet', category: 'Utility', handlerKey: 'openShortcutHelp' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Question-Mark Shortcut Never Matches

On common layouts such as US keyboards, pressing ? produces key === '?' with shiftKey === true. This definition requests no Shift modifier, so the exact modifier check rejects the event and the help modal does not open.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/utils/keyboardShortcuts.ts
Line: 127

Comment:
**Question-Mark Shortcut Never Matches**

On common layouts such as US keyboards, pressing `?` produces `key === '?'` with `shiftKey === true`. This definition requests no Shift modifier, so the exact modifier check rejects the event and the help modal does not open.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread frontend/src/App.tsx
openManeuverPlanning: () => navigate('/dashboard/mission-planner'),

// Search
openGlobalSearch: () => setGlobalSearchOpen(true),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Global Search Has No Consumer

Pressing Ctrl/Cmd+K prevents the browser default and sets globalSearchOpen, but no rendered component reads that state. The advertised shortcut therefore has no visible effect while also taking over the browser shortcut.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/App.tsx
Line: 52

Comment:
**Global Search Has No Consumer**

Pressing Ctrl/Cmd+K prevents the browser default and sets `globalSearchOpen`, but no rendered component reads that state. The advertised shortcut therefore has no visible effect while also taking over the browser shortcut.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread frontend/src/App.tsx
Comment on lines +43 to +49
openGlobeView: () => navigate('/dashboard'),
goToDashboard: () => navigate('/dashboard'),
goHome: () => navigate('/dashboard'),
openSatelliteManagement: () => navigate('/dashboard/satellites'),
openCollisionPrediction: () => navigate('/dashboard/collision-center'),
openAiAgentDashboard: () => navigate('/dashboard/ai-agents'),
openManeuverPlanning: () => navigate('/dashboard/mission-planner'),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Dashboard Keys Leak Across Routes

GlobalShortcuts is mounted outside the route layouts, so these unmodified letter shortcuts remain active on marketing and authentication pages. Pressing S, G, D, C, A, M, or H while no input is focused unexpectedly leaves the current public page and navigates into the dashboard.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/App.tsx
Line: 43-49

Comment:
**Dashboard Keys Leak Across Routes**

`GlobalShortcuts` is mounted outside the route layouts, so these unmodified letter shortcuts remain active on marketing and authentication pages. Pressing `S`, `G`, `D`, `C`, `A`, `M`, or `H` while no input is focused unexpectedly leaves the current public page and navigates into the dashboard.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +27 to +31
useEffect(() => {
if (!isOpen) return;
const previouslyFocused = document.activeElement as HTMLElement | null;
dialogRef.current?.focus();
return () => previouslyFocused?.focus();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Modal Focus Escapes Backdrop

This effect moves focus into the dialog but does not keep it there. A keyboard user can Tab past the modal controls into interactive content behind the backdrop, even though the dialog declares aria-modal="true".

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/components/ShortcutHelpModal.tsx
Line: 27-31

Comment:
**Modal Focus Escapes Backdrop**

This effect moves focus into the dialog but does not keep it there. A keyboard user can Tab past the modal controls into interactive content behind the backdrop, even though the dialog declares `aria-modal="true"`.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +90 to +95
// Data Actions — refresh wired via React Query cache invalidation at App level.
{ id: 'data-refresh', combo: { key: 'r', modifiers: ['ctrl'] }, description: 'Refresh current data', category: 'Data Actions', handlerKey: 'refreshCurrentData' },
{ id: 'data-force-refresh', combo: { key: 'r', modifiers: ['ctrl', 'shift'] }, description: 'Force refresh all live data', category: 'Data Actions', handlerKey: 'forceRefreshAllData' },
{ id: 'data-export', combo: { key: 'e', modifiers: ['ctrl'] }, description: 'Export current table', category: 'Data Actions', handlerKey: 'exportCurrentTable' },
{ id: 'data-export-all', combo: { key: 'e', modifiers: ['ctrl', 'shift'] }, description: 'Export all records', category: 'Data Actions', handlerKey: 'exportAllRecords' },
{ id: 'data-save', combo: { key: 's', modifiers: ['ctrl'] }, description: 'Save settings where applicable', category: 'Data Actions', handlerKey: 'saveSettings' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Help Lists Inactive Data Actions

The modal renders these entries from the global registry, but App.tsx registers only the two refresh handlers. Ctrl+E, Ctrl+Shift+E, and Ctrl+S therefore match a definition and then silently do nothing, so the cheat sheet advertises actions that are unavailable.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/utils/keyboardShortcuts.ts
Line: 90-95

Comment:
**Help Lists Inactive Data Actions**

The modal renders these entries from the global registry, but `App.tsx` registers only the two refresh handlers. Ctrl+E, Ctrl+Shift+E, and Ctrl+S therefore match a definition and then silently do nothing, so the cheat sheet advertises actions that are unavailable.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +98 to +107
{ id: 'table-up', combo: { key: 'ArrowUp' }, description: 'Move up a row', category: 'Table Navigation', handlerKey: 'tableMoveUp' },
{ id: 'table-down', combo: { key: 'ArrowDown' }, description: 'Move down a row', category: 'Table Navigation', handlerKey: 'tableMoveDown' },
{ id: 'table-left', combo: { key: 'ArrowLeft' }, description: 'Move left a column', category: 'Table Navigation', handlerKey: 'tableMoveLeft' },
{ id: 'table-right', combo: { key: 'ArrowRight' }, description: 'Move right a column', category: 'Table Navigation', handlerKey: 'tableMoveRight' },
{ id: 'table-open', combo: { key: 'Enter' }, description: 'Open selected item', category: 'Table Navigation', handlerKey: 'tableOpenSelected' },
{ id: 'table-clear-filters', combo: { key: 'Delete' }, description: 'Clear filters', category: 'Table Navigation', handlerKey: 'tableClearFilters' },
{ id: 'table-first-row', combo: { key: 'Home' }, description: 'Jump to first row', category: 'Table Navigation', handlerKey: 'tableJumpToFirstRow' },
{ id: 'table-last-row', combo: { key: 'End' }, description: 'Jump to last row', category: 'Table Navigation', handlerKey: 'tableJumpToLastRow' },
{ id: 'table-page-up', combo: { key: 'PageUp' }, description: 'Previous page', category: 'Table Navigation', handlerKey: 'tablePageUp' },
{ id: 'table-page-down', combo: { key: 'PageDown' }, description: 'Next page', category: 'Table Navigation', handlerKey: 'tablePageDown' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Table Shortcuts Have No Registration Path

Every table command is displayed in the help modal, but the only hook instance uses the global definitions and supplies none of these handlers. No page registers a scoped shortcut hook, so all ten advertised table shortcuts are reachable no-ops.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/utils/keyboardShortcuts.ts
Line: 98-107

Comment:
**Table Shortcuts Have No Registration Path**

Every table command is displayed in the help modal, but the only hook instance uses the global definitions and supplies none of these handlers. No page registers a scoped shortcut hook, so all ten advertised table shortcuts are reachable no-ops.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +110 to +116
{ id: 'globe-zoom-in', combo: { key: '+' }, description: 'Zoom in', category: 'Globe Controls', handlerKey: 'globeZoomIn' },
{ id: 'globe-zoom-out', combo: { key: '-' }, description: 'Zoom out', category: 'Globe Controls', handlerKey: 'globeZoomOut' },
{ id: 'globe-reset-camera', combo: { key: '0' }, description: 'Reset camera', category: 'Globe Controls', handlerKey: 'globeResetCamera' },
{ id: 'globe-toggle-labels', combo: { key: 'l' }, description: 'Toggle labels', category: 'Globe Controls', handlerKey: 'globeToggleLabels' },
{ id: 'globe-toggle-debris', combo: { key: 'b' }, description: 'Toggle debris visibility', category: 'Globe Controls', handlerKey: 'globeToggleDebris' },
{ id: 'globe-toggle-orbits', combo: { key: 'o' }, description: 'Toggle orbit paths', category: 'Globe Controls', handlerKey: 'globeToggleOrbits' },
{ id: 'globe-focus-satellite', combo: { key: 'f' }, description: 'Focus selected satellite', category: 'Globe Controls', handlerKey: 'globeFocusSatellite' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Globe Shortcuts Are Unwired

These controls are shown as available in the help modal, but neither the global handler map nor the globe view registers their handler keys. Pressing the advertised zoom, camera, label, debris, orbit, or focus keys therefore produces no globe action.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/utils/keyboardShortcuts.ts
Line: 110-116

Comment:
**Globe Shortcuts Are Unwired**

These controls are shown as available in the help modal, but neither the global handler map nor the globe view registers their handler keys. Pressing the advertised zoom, camera, label, debris, orbit, or focus keys therefore produces no globe action.

How can I resolve this? If you propose a fix, please make it concise.

{ id: 'nav-risk', combo: { key: 'r' }, description: 'Open Risk Assessment', category: 'Navigation', handlerKey: 'openRiskAssessment' },
{ id: 'nav-prediction', combo: { key: 'p' }, description: 'Open Prediction Analytics', category: 'Navigation', handlerKey: 'openPredictionAnalytics' },
{ id: 'nav-home', combo: { key: 'h' }, description: 'Return to Home/Dashboard', category: 'Navigation', handlerKey: 'goHome' },
{ id: 'nav-close-modal', combo: { key: 'Escape' }, description: 'Close open modal or dialog', category: 'Navigation', handlerKey: 'closeModal', allowInTypingContext: true },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Escape Only Closes Help

The registry advertises Escape as closing an open modal or dialog, but the hook handles this key only when its own help modal is open and App.tsx supplies no general closeModal handler. Other application dialogs remain open when users invoke the advertised shortcut.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/utils/keyboardShortcuts.ts
Line: 83

Comment:
**Escape Only Closes Help**

The registry advertises Escape as closing an open modal or dialog, but the hook handles this key only when its own help modal is open and `App.tsx` supplies no general `closeModal` handler. Other application dialogs remain open when users invoke the advertised shortcut.

How can I resolve this? If you propose a fix, please make it concise.

}) => {
const dialogRef = useRef<HTMLDivElement>(null);

// Keep focus inside the modal while open, restore it on close.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This comment states focus is kept inside the modal, but the implementation only focuses the dialog once and restores prior focus on close; it does not trap Tab navigation. Update the comment to match behavior or implement an actual focus trap. [comment mismatch]

Severity Level: Minor 🧹
- ⚠️ Modal comment overstates accessibility behavior versus implementation.
- ⚠️ Developers may assume focus trapping that does not exist.
Steps of Reproduction ✅
1. Open the Kepler frontend so that `App` renders, which includes `GlobalShortcuts` and
the `ShortcutHelpModal` component (`frontend/src/App.tsx:34-63`).

2. Trigger the keyboard shortcut help modal using the working shortcut `Ctrl + /`, which
is defined as `util-help-slash` in `SHORTCUT_DEFINITIONS`
(`frontend/src/utils/keyboardShortcuts.ts:126`) and handled by `useKeyboardShortcuts`
(`frontend/src/hooks/useKeyboardShortcuts.ts:91-104`), causing `isHelpOpen` to become
`true` and `ShortcutHelpModal` to render (`App.tsx:63`).

3. When `ShortcutHelpModal` mounts with `isOpen` true, its `useEffect` hook at
`frontend/src/components/ShortcutHelpModal.tsx:26-32` runs: it stores
`document.activeElement` in `previouslyFocused`, calls `dialogRef.current?.focus()` once,
and returns a cleanup that restores the prior focus on close; no further keyboard or
focus-trap logic is implemented in this component.

4. While the modal is open, press `Tab` repeatedly: because there is no additional handler
(e.g., `onKeyDown`, focus-looping, or trapping via `tabIndex` management) in
`ShortcutHelpModal.tsx` beyond the initial `focus()` call, focus is free to move to other
focusable elements outside the modal, demonstrating that focus is not “kept inside the
modal” as the comment describes, so the comment is misleading relative to actual behavior.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** frontend/src/components/ShortcutHelpModal.tsx
**Line:** 26:26
**Comment:**
	*Comment Mismatch: This comment states focus is kept inside the modal, but the implementation only focuses the dialog once and restores prior focus on close; it does not trap `Tab` navigation. Update the comment to match behavior or implement an actual focus trap.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

{ id: 'table-page-down', combo: { key: 'PageDown' }, description: 'Next page', category: 'Table Navigation', handlerKey: 'tablePageDown' },

// Globe Controls — wired inside Dashboard/EarthTwin, not globally.
{ id: 'globe-zoom-in', combo: { key: '+' }, description: 'Zoom in', category: 'Globe Controls', handlerKey: 'globeZoomIn' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The + shortcut is also missing shift, but + requires Shift on standard keyboards and the hook rejects extra modifiers, so zoom-in will never trigger. Define this shortcut with modifiers: ['shift'] (or adjust matching logic for printable symbols). [incorrect condition logic]

Severity Level: Major ⚠️
- ⚠️ Planned globe zoom shortcut will not work with `+`.
- ⚠️ Future EarthTwin keyboard UX compromised until definition fixed.
Steps of Reproduction ✅
1. Inspect the globe controls shortcut definitions in
`frontend/src/utils/keyboardShortcuts.ts:109-117`, which include `{ id: 'globe-zoom-in',
combo: { key: '+' }, description: 'Zoom in', category: 'Globe Controls', handlerKey:
'globeZoomIn' }` at line 110, with no `modifiers` specified on the combo.

2. Observe the comment above these definitions: “Globe Controls — wired inside
Dashboard/EarthTwin, not globally.” (`keyboardShortcuts.ts:109), indicating the intent
that these shortcuts will be used with `useKeyboardShortcuts` in a page-specific context
once the EarthTwin/globe view wiring is added.

3. Examine the shortcut matching logic in `frontend/src/hooks/useKeyboardShortcuts.ts`:
`handleKeyDown` runs through `definitions` and applies `keyMatches(event, def.combo.key)`
(`hooks/useKeyboardShortcuts.ts:91-97) plus `modifiersMatch(event, def.combo.modifiers)`
(`hooks/useKeyboardShortcuts.ts:96-97). `modifiersMatch` computes `wantShift` from the
`modifiers` array and requires `wantShift === event.shiftKey`
(`hooks/useKeyboardShortcuts.ts:46-56), so any pressed modifier that is not listed causes
the match to fail.

4. On a standard keyboard, pressing the `+` key requires `Shift` (usually `Shift + '='`),
yielding a `KeyboardEvent` with `event.key === '+'` and `event.shiftKey === true`. Given
the current `globe-zoom-in` definition has `modifiers` undefined (treated as `[]`),
`keyMatches` would succeed but `modifiersMatch` would compute `wantShift === false` and
fail because `event.shiftKey === true`, preventing any future `globeZoomIn` handler from
ever firing when users press `+` to zoom. This means that once globe zoom-in is wired up
in an EarthTwin page using these definitions, the intended shortcut will be unreachable
until either `modifiers: ['shift']` is added to the combo or the matching logic is relaxed
for symbol keys.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** frontend/src/utils/keyboardShortcuts.ts
**Line:** 110:110
**Comment:**
	*Incorrect Condition Logic: The `+` shortcut is also missing `shift`, but `+` requires `Shift` on standard keyboards and the hook rejects extra modifiers, so zoom-in will never trigger. Define this shortcut with `modifiers: ['shift']` (or adjust matching logic for printable symbols).

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎


// Utility
{ id: 'util-help-slash', combo: { key: '/', modifiers: ['ctrl'] }, description: 'Open shortcut help', category: 'Utility', handlerKey: 'openShortcutHelp' },
{ id: 'util-help-question', combo: { key: '?' }, description: 'Show shortcut cheat sheet', category: 'Utility', handlerKey: 'openShortcutHelp' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The ? shortcut is defined without shift, but the matcher requires exact modifier parity, so pressing ? (which sets Shift) will never match and the help modal cannot be opened with that key. Add shift to this combo or relax modifier matching for symbol keys. [incorrect condition logic]

Severity Level: Major ⚠️
- ❌ Advertised `?` shortcut fails to open help modal.
- ⚠️ Users rely on help modal for shortcut discovery.
Steps of Reproduction ✅
1. Start the app so `App` renders `GlobalShortcuts`, which calls `useKeyboardShortcuts`
with handlers and uses the default `SHORTCUT_DEFINITIONS` (`frontend/src/App.tsx:34-61`,
`frontend/src/hooks/useKeyboardShortcuts.ts:77`).

2. Note that the shortcut definition for the help “?” key is `{ id: 'util-help-question',
combo: { key: '?' }, ... handlerKey: 'openShortcutHelp' }` in
`frontend/src/utils/keyboardShortcuts.ts:127`, with no `modifiers` array specified.

3. Observe the matching logic in `useKeyboardShortcuts`: `handleKeyDown` iterates
`definitions` and, for each `def`, calls `keyMatches(event, def.combo.key)`
(`hooks/useKeyboardShortcuts.ts:94-97`) and `modifiersMatch(event, def.combo.modifiers)`
(`hooks/useKeyboardShortcuts.ts:96-97). `modifiersMatch` computes desired modifiers from
the array and requires exact parity against `event.ctrlKey/metaKey`, `event.shiftKey`, and
`event.altKey` (`hooks/useKeyboardShortcuts.ts:46-57), defaulting `modifiers` to `[]`.

4. With the app focused, press `?` on a standard keyboard (Shift + `/`): the browser
dispatches a `KeyboardEvent` with `event.key === '?'` and `event.shiftKey === true`.
`keyMatches` returns true because the key strings match
(`hooks/useKeyboardShortcuts.ts:60-63), but `modifiersMatch` compares `wantShift` (false,
because `modifiers` is `[]`) to `event.shiftKey` (true) and returns false
(`hooks/useKeyboardShortcuts.ts:48-56). As a result, the `handlerKey ===
'openShortcutHelp'` branch (`hooks/useKeyboardShortcuts.ts:99-103) never executes, the
`isHelpOpen` state is not toggled, and the help modal does not open via `?`, even though
the footer of `ShortcutHelpModal` advertises “Press ? or Ctrl + / anytime to reopen this”
(`frontend/src/components/ShortcutHelpModal.tsx:108-110).

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** frontend/src/utils/keyboardShortcuts.ts
**Line:** 127:127
**Comment:**
	*Incorrect Condition Logic: The `?` shortcut is defined without `shift`, but the matcher requires exact modifier parity, so pressing `?` (which sets `Shift`) will never match and the help modal cannot be opened with that key. Add `shift` to this combo or relax modifier matching for symbol keys.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
frontend/src/components/ShortcutHelpModal.tsx (1)

27-32: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Modal has no Tab-key focus trap.

Focus is placed on the dialog when it opens and restored on close, but nothing stops Tab/Shift+Tab from moving focus out into the background page while the modal is open, since only Escape/backdrop-click close it.

Proposed fix: trap Tab within the dialog
   useEffect(() => {
     if (!isOpen) return;
     const previouslyFocused = document.activeElement as HTMLElement | null;
     dialogRef.current?.focus();
-    return () => previouslyFocused?.focus();
+    const handleTabTrap = (e: KeyboardEvent) => {
+      if (e.key !== 'Tab' || !dialogRef.current) return;
+      const focusables = dialogRef.current.querySelectorAll<HTMLElement>(
+        'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
+      );
+      if (!focusables.length) return;
+      const first = focusables[0];
+      const last = focusables[focusables.length - 1];
+      if (e.shiftKey && document.activeElement === first) {
+        e.preventDefault();
+        last.focus();
+      } else if (!e.shiftKey && document.activeElement === last) {
+        e.preventDefault();
+        first.focus();
+      }
+    };
+    document.addEventListener('keydown', handleTabTrap);
+    return () => {
+      document.removeEventListener('keydown', handleTabTrap);
+      previouslyFocused?.focus();
+    };
   }, [isOpen]);
🤖 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 `@frontend/src/components/ShortcutHelpModal.tsx` around lines 27 - 32, Update
the focus-management useEffect in ShortcutHelpModal to add a keydown handler
while the modal is open that traps Tab and Shift+Tab within the dialog’s
focusable descendants, wrapping forward from the last element to the first and
backward from the first to the last. Register and clean up the handler with the
existing effect, while preserving focus restoration on close.
frontend/src/hooks/useKeyboardShortcuts.ts (1)

18-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider a typed handlerKey union instead of bare string.

ShortcutHandlers accepts any string key, so a typo in the handlers map passed from App.tsx (e.g. misspelling openGlobalSearch) compiles fine but silently never fires. Deriving a union from SHORTCUT_DEFINITIONS would catch this at compile time.

Proposed refactor
-export type ShortcutHandlers = Partial<Record<string, () => void>>;
+export type ShortcutHandlerKey = (typeof SHORTCUT_DEFINITIONS)[number]['handlerKey'];
+export type ShortcutHandlers = Partial<Record<ShortcutHandlerKey, () => void>>;

(requires SHORTCUT_DEFINITIONS to be declared as const in keyboardShortcuts.ts for the literal union to be inferred.)

🤖 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 `@frontend/src/hooks/useKeyboardShortcuts.ts` around lines 18 - 25, Replace the
bare string key in ShortcutHandlers with a literal handlerKey union derived from
the readonly SHORTCUT_DEFINITIONS declaration, ensuring SHORTCUT_DEFINITIONS is
declared as const so its handler keys remain literals. Update the related
ShortcutDefinition typing as needed while preserving the existing handler lookup
and custom definitions behavior.
🤖 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 `@frontend/src/App.tsx`:
- Around line 34-64: Scope GlobalShortcuts to dashboard routes by importing and
using useLocation alongside useNavigate, then pass the existing disabled option
to useKeyboardShortcuts when the current pathname is outside /dashboard
(including marketing and authentication pages). Preserve all shortcut handlers
for dashboard routes.
- Around line 39-61: Wire the existing openSettings shortcut in the
useKeyboardShortcuts configuration by navigating to the /dashboard/settings
route, alongside the other navigation handlers. Keep the documented no-op scope
limited to routes that do not yet exist.

In `@frontend/src/utils/keyboardShortcuts.ts`:
- Around line 118-124: Update the dash-toggle-theme shortcut in the keyboard
shortcut definitions to use a non-browser-reserved key combination instead of
Ctrl+T, avoiding both Ctrl+T and Ctrl+Shift+T while preserving its toggleTheme
handler and dashboard-controls metadata.

---

Nitpick comments:
In `@frontend/src/components/ShortcutHelpModal.tsx`:
- Around line 27-32: Update the focus-management useEffect in ShortcutHelpModal
to add a keydown handler while the modal is open that traps Tab and Shift+Tab
within the dialog’s focusable descendants, wrapping forward from the last
element to the first and backward from the first to the last. Register and clean
up the handler with the existing effect, while preserving focus restoration on
close.

In `@frontend/src/hooks/useKeyboardShortcuts.ts`:
- Around line 18-25: Replace the bare string key in ShortcutHandlers with a
literal handlerKey union derived from the readonly SHORTCUT_DEFINITIONS
declaration, ensuring SHORTCUT_DEFINITIONS is declared as const so its handler
keys remain literals. Update the related ShortcutDefinition typing as needed
while preserving the existing handler lookup and custom definitions behavior.
🪄 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 Plus

Run ID: b2a5a164-daee-40e7-9e74-c8324d3d7828

📥 Commits

Reviewing files that changed from the base of the PR and between 2510ede and 1406b45.

📒 Files selected for processing (4)
  • frontend/src/App.tsx
  • frontend/src/components/ShortcutHelpModal.tsx
  • frontend/src/hooks/useKeyboardShortcuts.ts
  • frontend/src/utils/keyboardShortcuts.ts

Comment thread frontend/src/App.tsx
Comment on lines +34 to +64
function GlobalShortcuts() {
const navigate = useNavigate();
const queryClient = useQueryClient();
const { toggleSidebar, setGlobalSearchOpen } = useUIStore();

const { isHelpOpen, closeHelp, isMac } = useKeyboardShortcuts({
// Navigation — routes that exist today. Telemetry / Space Weather /
// Risk Assessment / Prediction Analytics have no page yet, so those
// shortcuts are left unwired (safe no-ops) until those routes land.
openGlobeView: () => navigate('/dashboard'),
goToDashboard: () => navigate('/dashboard'),
goHome: () => navigate('/dashboard'),
openSatelliteManagement: () => navigate('/dashboard/satellites'),
openCollisionPrediction: () => navigate('/dashboard/collision-center'),
openAiAgentDashboard: () => navigate('/dashboard/ai-agents'),
openManeuverPlanning: () => navigate('/dashboard/mission-planner'),

// Search
openGlobalSearch: () => setGlobalSearchOpen(true),

// Data actions — generic refresh via React Query's cache.
refreshCurrentData: () => queryClient.invalidateQueries(),
forceRefreshAllData: () =>
queryClient.invalidateQueries({ refetchType: 'all' }),

// Dashboard controls
toggleSidebar: () => toggleSidebar(),
});

return <ShortcutHelpModal isOpen={isHelpOpen} onClose={closeHelp} isMac={isMac} />;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Global shortcuts fire on marketing/auth pages too, not just the dashboard.

<GlobalShortcuts /> is mounted above <Routes>, so all single-letter navigation shortcuts (g/d/s/c/a/h/etc.) are live on /, /about, /docs, /signin, /signup, etc. A visitor reading the landing page or about to sign in can press a plain letter key and get redirected into /dashboard/... unexpectedly, since isTypingContext only guards actively-focused inputs, not "no input focused yet."

Proposed fix: scope shortcuts to dashboard routes via the existing `disabled` option
 function GlobalShortcuts() {
   const navigate = useNavigate();
   const queryClient = useQueryClient();
+  const location = useLocation();
   const { toggleSidebar, setGlobalSearchOpen } = useUIStore();

-  const { isHelpOpen, closeHelp, isMac } = useKeyboardShortcuts({
+  const { isHelpOpen, closeHelp, isMac } = useKeyboardShortcuts({
     openGlobeView: () => navigate('/dashboard'),
     ...
     toggleSidebar: () => toggleSidebar(),
-  });
+  }, { disabled: !location.pathname.startsWith('/dashboard') });

(useLocation needs importing from react-router-dom alongside the existing useNavigate import.)

Also applies to: 74-74

🤖 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 `@frontend/src/App.tsx` around lines 34 - 64, Scope GlobalShortcuts to
dashboard routes by importing and using useLocation alongside useNavigate, then
pass the existing disabled option to useKeyboardShortcuts when the current
pathname is outside /dashboard (including marketing and authentication pages).
Preserve all shortcut handlers for dashboard routes.

Comment thread frontend/src/App.tsx
Comment on lines +39 to +61
const { isHelpOpen, closeHelp, isMac } = useKeyboardShortcuts({
// Navigation — routes that exist today. Telemetry / Space Weather /
// Risk Assessment / Prediction Analytics have no page yet, so those
// shortcuts are left unwired (safe no-ops) until those routes land.
openGlobeView: () => navigate('/dashboard'),
goToDashboard: () => navigate('/dashboard'),
goHome: () => navigate('/dashboard'),
openSatelliteManagement: () => navigate('/dashboard/satellites'),
openCollisionPrediction: () => navigate('/dashboard/collision-center'),
openAiAgentDashboard: () => navigate('/dashboard/ai-agents'),
openManeuverPlanning: () => navigate('/dashboard/mission-planner'),

// Search
openGlobalSearch: () => setGlobalSearchOpen(true),

// Data actions — generic refresh via React Query's cache.
refreshCurrentData: () => queryClient.invalidateQueries(),
forceRefreshAllData: () =>
queryClient.invalidateQueries({ refetchType: 'all' }),

// Dashboard controls
toggleSidebar: () => toggleSidebar(),
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

openSettings isn't wired despite the Settings route existing.

Unlike Telemetry/Space Weather/Risk/Prediction (explicitly documented as unwired because those pages don't exist yet), /dashboard/settings already exists (line 97) but util-settings (Ctrl+Shift+S, handlerKey: 'openSettings') has no handler here, so the shortcut is a silent no-op.

Proposed fix
     // Dashboard controls
     toggleSidebar: () => toggleSidebar(),
+
+    // Utility
+    openSettings: () => navigate('/dashboard/settings'),
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { isHelpOpen, closeHelp, isMac } = useKeyboardShortcuts({
// Navigation — routes that exist today. Telemetry / Space Weather /
// Risk Assessment / Prediction Analytics have no page yet, so those
// shortcuts are left unwired (safe no-ops) until those routes land.
openGlobeView: () => navigate('/dashboard'),
goToDashboard: () => navigate('/dashboard'),
goHome: () => navigate('/dashboard'),
openSatelliteManagement: () => navigate('/dashboard/satellites'),
openCollisionPrediction: () => navigate('/dashboard/collision-center'),
openAiAgentDashboard: () => navigate('/dashboard/ai-agents'),
openManeuverPlanning: () => navigate('/dashboard/mission-planner'),
// Search
openGlobalSearch: () => setGlobalSearchOpen(true),
// Data actions — generic refresh via React Query's cache.
refreshCurrentData: () => queryClient.invalidateQueries(),
forceRefreshAllData: () =>
queryClient.invalidateQueries({ refetchType: 'all' }),
// Dashboard controls
toggleSidebar: () => toggleSidebar(),
});
const { isHelpOpen, closeHelp, isMac } = useKeyboardShortcuts({
// Navigation — routes that exist today. Telemetry / Space Weather /
// Risk Assessment / Prediction Analytics have no page yet, so those
// shortcuts are left unwired (safe no-ops) until those routes land.
openGlobeView: () => navigate('/dashboard'),
goToDashboard: () => navigate('/dashboard'),
goHome: () => navigate('/dashboard'),
openSatelliteManagement: () => navigate('/dashboard/satellites'),
openCollisionPrediction: () => navigate('/dashboard/collision-center'),
openAiAgentDashboard: () => navigate('/dashboard/ai-agents'),
openManeuverPlanning: () => navigate('/dashboard/mission-planner'),
// Search
openGlobalSearch: () => setGlobalSearchOpen(true),
// Data actions — generic refresh via React Query's cache.
refreshCurrentData: () => queryClient.invalidateQueries(),
forceRefreshAllData: () =>
queryClient.invalidateQueries({ refetchType: 'all' }),
// Dashboard controls
toggleSidebar: () => toggleSidebar(),
// Utility
openSettings: () => navigate('/dashboard/settings'),
});
🤖 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 `@frontend/src/App.tsx` around lines 39 - 61, Wire the existing openSettings
shortcut in the useKeyboardShortcuts configuration by navigating to the
/dashboard/settings route, alongside the other navigation handlers. Keep the
documented no-op scope limited to routes that do not yet exist.

Comment on lines +118 to +124
// Dashboard Controls — sidebar toggle wired to the existing uiStore.
{ id: 'dash-toggle-sidebar', combo: { key: 'd', modifiers: ['ctrl'] }, description: 'Toggle sidebar', category: 'Dashboard Controls', handlerKey: 'toggleSidebar' },
{ id: 'dash-collapse-sidebar', combo: { key: 'b', modifiers: ['ctrl'] }, description: 'Collapse or expand sidebar', category: 'Dashboard Controls', handlerKey: 'toggleSidebar' },
{ id: 'dash-toggle-fullscreen', combo: { key: 'd', modifiers: ['ctrl', 'shift'] }, description: 'Toggle fullscreen dashboard', category: 'Dashboard Controls', handlerKey: 'toggleFullscreenDashboard' },
{ id: 'dash-toggle-theme', combo: { key: 't', modifiers: ['ctrl'] }, description: 'Toggle theme', category: 'Dashboard Controls', handlerKey: 'toggleTheme' },
{ id: 'dash-toggle-live', combo: { key: 'l', modifiers: ['ctrl'] }, description: 'Toggle live updates', category: 'Dashboard Controls', handlerKey: 'toggleLiveUpdates' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the file and inspect the relevant sections with line numbers.
wc -l frontend/src/utils/keyboardShortcuts.ts
sed -n '1,220p' frontend/src/utils/keyboardShortcuts.ts | cat -n

# Find where the dashboard shortcuts are referenced elsewhere.
rg -n "dash-toggle-theme|toggleTheme|dash-toggle-sidebar|dash-toggle-fullscreen|dash-toggle-live|dash-collapse-sidebar" frontend

Repository: 7-Blocks/Kepler

Length of output: 12760


Avoid browser-reserved shortcuts for theme toggle. Ctrl+T is intercepted by the browser for “new tab”, and Ctrl+Shift+T is also reserved in most browsers. Use a non-reserved combo here.

🤖 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 `@frontend/src/utils/keyboardShortcuts.ts` around lines 118 - 124, Update the
dash-toggle-theme shortcut in the keyboard shortcut definitions to use a
non-browser-reserved key combination instead of Ctrl+T, avoiding both Ctrl+T and
Ctrl+Shift+T while preserving its toggleTheme handler and dashboard-controls
metadata.

@krishkhinchi krishkhinchi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM!!

@krishkhinchi
krishkhinchi merged commit 72631d9 into 7-Blocks:main Jul 22, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Artificial Intelligence and Machine Learning bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request frontend Frontend development size/L Large contribution requiring significant work. size:L Large size type:bug Fixes an existing bug or unexpected behavior. type:documentation Improves project documentation. type:feature Introduces a new feature or enhancement. type:frontend Changes frontend or client-side code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

⌨️ Add Global Keyboard Shortcuts for Faster Navigation and Productivity

2 participants