Skip to content

feat(desktop): add help menu to top bar#259

Merged
Kitenite merged 6 commits intomainfrom
cheap-crane-107610
Dec 6, 2025
Merged

feat(desktop): add help menu to top bar#259
Kitenite merged 6 commits intomainfrom
cheap-crane-107610

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Dec 5, 2025

Summary

  • Add a HelpMenu component to the desktop app top bar
  • Provides quick access to Contact Us (email), Report Issue (GitHub), Join Discord, and Keyboard Shortcuts
  • Follows existing UI patterns with dropdown menu and icons

Test plan

  • Verify help menu icon appears in top bar
  • Test Contact Us opens email client
  • Test Report Issue opens GitHub issues page
  • Test Join Discord opens Discord invite link
  • Test Keyboard Shortcuts opens settings to keyboard section

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a Help menu in the top navigation offering Contact Support, Report Issue, Join Discord, and a Keyboard Shortcuts view that displays current hotkeys.
    • Added matching Help entries to the app's native/system menu so support links and the keyboard-shortcuts view are accessible from the OS menu.

✏️ Tip: You can customize this high-level summary in your review settings.

Add a HelpMenu component with quick access to:
- Contact Us (email)
- Report Issue (GitHub issues)
- Join Discord
- Keyboard Shortcuts (opens settings)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 5, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
website Ready Ready Preview Comment Dec 6, 2025 8:38am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 5, 2025

Warning

Rate limit exceeded

@Kitenite has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 16 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 1d76124 and e87d287.

📒 Files selected for processing (8)
  • apps/desktop/src/lib/trpc/routers/index.ts (2 hunks)
  • apps/desktop/src/lib/trpc/routers/menu.ts (1 hunks)
  • apps/desktop/src/main/lib/menu-events.ts (1 hunks)
  • apps/desktop/src/main/lib/menu.ts (2 hunks)
  • apps/desktop/src/main/windows/main.ts (1 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx (2 hunks)
  • apps/desktop/src/renderer/screens/main/index.tsx (1 hunks)
  • apps/desktop/src/shared/constants.ts (1 hunks)

Walkthrough

Adds a HelpMenu React dropdown to the TopBar, a new HELP_MENU constant, a Help top-level menu in the Electron main menu that opens external links or sends IPC, and an IPC listener in the renderer to open the keyboard settings.

Changes

Cohort / File(s) Summary
Help menu UI
apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx, apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/index.ts
New HelpMenu component and re-export. Renders a help-icon dropdown with items: Contact Us, Report Issue, Join Discord (open external URLs), and Keyboard Shortcuts (calls openSettings("keyboard")); displays hotkeys via formatKeysForDisplay/KbdGroup.
TopBar integration
apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx
Imports and renders <HelpMenu /> in the TopBar layout.
Main-process menu & IPC
apps/desktop/src/main/lib/menu.ts, apps/desktop/src/renderer/screens/main/index.tsx
Adds a Help top-level menu with items that call shell.openExternal(...) or send IPC menu:open-settings; renderer listens for menu:open-settings and invokes openSettings("keyboard") (with lifecycle cleanup).
Constants
apps/desktop/src/shared/constants.ts
Adds exported HELP_MENU constant containing CONTACT_EMAIL, REPORT_ISSUE_URL, and DISCORD_URL.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant Renderer as Renderer (TopBar / HelpMenu)
    participant Main as Main (Electron menu)
    participant Shell as Shell (shell.openExternal)
    User->>Renderer: Clicks Help icon, selects menu item
    alt External link selected
        Renderer->>Main: (if via app menu) Main handles action
        Main->>Shell: shell.openExternal(URL)
        Shell-->>User: Browser opens URL
    else Keyboard Shortcuts selected
        alt Triggered from renderer UI
            Renderer->>Renderer: openSettings("keyboard")
            Renderer-->>User: Show Settings → Keyboard
        else Triggered from main menu
            Main->>Renderer: send IPC `menu:open-settings`
            Renderer->>Renderer: openSettings("keyboard")
            Renderer-->>User: Show Settings → Keyboard
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Pay extra attention to:
    • apps/desktop/src/main/lib/menu.ts — menu template placement and cross-platform behavior.
    • apps/desktop/src/renderer/screens/main/index.tsx — IPC listener typing and cleanup.
    • HelpMenu.tsx — hotkey display formatting and external URL usages.

Possibly related PRs

Poem

"A rabbit hops to show the way, 🐇
A question-mark lights up the day, ❓
Links and keys for every quest, 🔗⌨️
Click, open, and find what's best —
Hop along and press!"

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides a clear summary of changes and includes a test plan, but does not follow the repository's description template structure with required sections like Related Issues, Type of Change, Testing, and Screenshots. Restructure the description to match the template: add Related Issues section, explicitly mark 'New feature' in Type of Change, expand Testing section with detailed steps, and include any applicable screenshots or additional notes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(desktop): add help menu to top bar' accurately and concisely summarizes the main change: adding a new HelpMenu component to the desktop app's top bar.

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.

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fe2672 and dc1fc3a.

📒 Files selected for processing (3)
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx (1 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/index.ts (1 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/index.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid using any type - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/index.ts
**/components/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

**/components/**/*.tsx: Create one folder per component with structure: ComponentName/ComponentName.tsx + index.ts for barrel export
Co-locate tests next to the component file they test (e.g., ComponentName.test.tsx)
Co-locate dependencies (utils, hooks, constants, config, stories) next to the file using them
Use nested components/ subdirectory within a parent component only if a sub-component is used 2+ times within that parent; otherwise keep it in the parent's components/ folder
One component per file - avoid multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/index.ts
apps/desktop/src/renderer/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Call IPC methods using window.ipcRenderer.invoke() with object parameters - TypeScript will infer the exact response type automatically

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx
🧬 Code graph analysis (2)
apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx (2)
apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx (1)
  • HelpMenu (23-80)
apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/index.ts (1)
  • HelpMenu (1-1)
apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx (4)
apps/desktop/src/renderer/stores/app-state.ts (1)
  • useOpenSettings (65-65)
apps/desktop/src/shared/hotkeys.ts (2)
  • formatKeysForDisplay (197-220)
  • HOTKEYS (28-168)
packages/ui/src/components/dropdown-menu.tsx (5)
  • DropdownMenu (245-245)
  • DropdownMenuTrigger (247-247)
  • DropdownMenuContent (248-248)
  • DropdownMenuItem (251-251)
  • DropdownMenuSeparator (255-255)
packages/ui/src/components/kbd.tsx (2)
  • KbdGroup (28-28)
  • Kbd (28-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (5)
apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx (3)

1-17: LGTM!

Imports are correctly structured, using proper aliases and following the renderer process guidelines.


31-41: LGTM!

The handlers for external URLs and settings navigation are correctly implemented.


43-79: LGTM!

The dropdown menu structure follows existing UI patterns correctly, with proper accessibility attributes and keyboard shortcut display.

apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx (1)

3-3: LGTM!

The HelpMenu integration follows existing patterns and is correctly placed in the TopBar alongside other control buttons.

Also applies to: 28-28

apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/index.ts (1)

1-1: LGTM!

The barrel export follows the component structure guidelines correctly.

Comment thread apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx Outdated
Comment on lines +27 to +29
const handleContactUs = () => {
window.open(CONTACT_EMAIL, "_blank");
};
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.

⚠️ Potential issue | 🟡 Minor

Fix incorrect mailto: link handling.

Using window.open with a mailto: link and "_blank" target is incorrect. Mailto links open the user's default email client and don't work with window targets.

Apply this diff to fix the handler:

 const handleContactUs = () => {
-	window.open(CONTACT_EMAIL, "_blank");
+	window.location.href = CONTACT_EMAIL;
 };
📝 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 handleContactUs = () => {
window.open(CONTACT_EMAIL, "_blank");
};
const handleContactUs = () => {
window.location.href = CONTACT_EMAIL;
};
🤖 Prompt for AI Agents
In
apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx
around lines 27 to 29, the handler opens a mailto link with window.open(...,
"_blank") which is incorrect; change it to navigate the current window to a
properly formed mailto URL. Build the mailto string (prepend "mailto:" if
CONTACT_EMAIL doesn't already start with it) and assign it to
window.location.href (or use window.location.assign) so the user's default email
client is launched.

- Extract help menu URLs to shared/constants.ts (HELP_MENU)
- Update HelpMenu.tsx to use shared constants
- Add Help menu to Mac application menu bar with:
  - Contact Us (opens email)
  - Report Issue (opens GitHub issues)
  - Join Discord
  - Keyboard Shortcuts (opens settings)
- Add IPC listener in MainScreen for menu:open-settings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
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: 1

🧹 Nitpick comments (2)
apps/desktop/src/shared/constants.ts (1)

32-37: Centralized HELP_MENU URLs look good and match usage

Defining HELP_MENU here with as const is a clean way to keep Help-related URLs in sync between main and renderer. This should reduce duplication and drift (e.g., between the native Help menu and the TopBar HelpMenu component).

If you ever need staging/enterprise overrides, these can be made environment-driven later, but the current shape is solid for now.

apps/desktop/src/main/lib/menu.ts (1)

1-2: Help menu wiring is correct; minor optional deduplication possible

The new Help menu looks solid:

  • shell.openExternal is correctly used for HELP_MENU.CONTACT_EMAIL, REPORT_ISSUE_URL, and DISCORD_URL.
  • The "Keyboard Shortcuts" item sending mainWindow.webContents.send("menu:open-settings", "keyboard") aligns with the SettingsSection "keyboard" value and the renderer listener (once its handler signature is fixed).

If you want to reduce repetition, you could optionally factor the three external-link items through a tiny helper to keep things DRY, but that’s not required:

-				{
-					label: "Contact Us",
-					click: () => {
-						shell.openExternal(HELP_MENU.CONTACT_EMAIL);
-					},
-				},
+				{
+					label: "Contact Us",
+					click: () => shell.openExternal(HELP_MENU.CONTACT_EMAIL),
+				},

Same pattern could be applied to the other two links for brevity.

Also applies to: 60-89

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc1fc3a and dcccf76.

📒 Files selected for processing (4)
  • apps/desktop/src/main/lib/menu.ts (2 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx (1 hunks)
  • apps/desktop/src/renderer/screens/main/index.tsx (2 hunks)
  • apps/desktop/src/shared/constants.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/screens/main/components/TopBar/HelpMenu/HelpMenu.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/shared/constants.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/main/lib/menu.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/shared/constants.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/main/lib/menu.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid using any type - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code

Files:

  • apps/desktop/src/shared/constants.ts
  • apps/desktop/src/renderer/screens/main/index.tsx
  • apps/desktop/src/main/lib/menu.ts
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only

Files:

  • apps/desktop/src/renderer/screens/main/index.tsx
apps/desktop/src/renderer/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Call IPC methods using window.ipcRenderer.invoke() with object parameters - TypeScript will infer the exact response type automatically

Files:

  • apps/desktop/src/renderer/screens/main/index.tsx
apps/desktop/src/main/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js modules (fs, path, os, net, etc.) can be used in main process code only

Files:

  • apps/desktop/src/main/lib/menu.ts
🧠 Learnings (3)
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to apps/desktop/src/renderer/**/*.tsx : Call IPC methods using `window.ipcRenderer.invoke()` with object parameters - TypeScript will infer the exact response type automatically

Applied to files:

  • apps/desktop/src/renderer/screens/main/index.tsx
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to apps/desktop/src/main/lib/*-ipcs.ts : IPC handlers must accept a single object parameter, not positional parameters, to match type-safe renderer calls

Applied to files:

  • apps/desktop/src/renderer/screens/main/index.tsx
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Applied to files:

  • apps/desktop/src/renderer/screens/main/index.tsx
🧬 Code graph analysis (2)
apps/desktop/src/renderer/screens/main/index.tsx (1)
apps/desktop/src/renderer/stores/app-state.ts (1)
  • SettingsSection (5-9)
apps/desktop/src/main/lib/menu.ts (1)
apps/desktop/src/shared/constants.ts (1)
  • HELP_MENU (33-37)

Comment thread apps/desktop/src/renderer/screens/main/index.tsx Outdated
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Replace raw IPC communication with trpc subscription pattern:
- Add menu-events.ts with EventEmitter for menu commands
- Add menu.ts trpc router with subscription for open-settings event
- Update menu.ts to emit events via menuEmitter instead of webContents.send
- Update MainScreen to use trpc.menu.subscribe instead of IPC listener
- Remove unused mainWindow parameter from createApplicationMenu

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Keep both improvements:
- Our createApplicationMenu() without window (uses trpc menuEmitter)
- Main's getWindow getter pattern and singleton IPC handler for macOS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
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