Skip to content

ui(desktop): new button with shortcuts option#460

Merged
AviPeltz merged 5 commits intomainfrom
mental-whale-00f71c
Dec 27, 2025
Merged

ui(desktop): new button with shortcuts option#460
AviPeltz merged 5 commits intomainfrom
mental-whale-00f71c

Conversation

@AviPeltz
Copy link
Copy Markdown
Collaborator

@AviPeltz AviPeltz commented Dec 21, 2025

Summary

  • Added keyboard shortcuts for workspace operations: create workspace (⌘N), quick create (⌘⇧N), and open project (⌘⇧O)
  • Redesigned workspace creation interface with dropdown menu offering multiple actions
  • Position the new workspace button absolutely at the right side with a gradient fade effect
  • Button now sticks at the right edge when tabs overflow, with smooth fade transition
  • Increased plus icon size (15px → 18px) and matched color with settings icon

Type of Change

  • New feature
  • Refactor

Test plan

  • Verify button is visible and properly positioned at the right of the tabs
  • Add multiple workspaces to trigger overflow and confirm button stays fixed at right
  • Check gradient fade appears when tabs overflow
  • Verify button color matches settings icon color
  • Test keyboard shortcuts work correctly

Screenshots

Screen.Recording.2025-12-21.at.2.54.15.PM.mov

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Replaced the single add button with a dropdown menu for workspace actions: New Workspace, Quick Create, and Open Project.
    • Added keyboard shortcuts: New workspace (⌘N), Quick create (⌘⇧N), Open project (⌘⇧O).
  • UI/UX Improvements

    • Right-aligned, compact add control with conditional fade indicators and improved alignment.
    • Menu shows keyboard hints and icons; actions reflect loading/disabled states and provide clearer error feedback.

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 21, 2025

📝 Walkthrough

Walkthrough

Replaces the workspace add ButtonGroup with a DropdownMenu UI, adds three workspace-related hotkeys, centralizes create/open/quick-create handlers with new loading/error flows, and moves the create control into a fixed right-side strip outside the tab scroll area.

Changes

Cohort / File(s) Summary
Workspace creation UI refactor
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
Replaced Button/ButtonGroup with DropdownMenu components and items; removed ref-based focus logic in favor of local open state; added useHotkeys bindings; rewrote handlers (handleModalCreate, handleQuickCreate, handleOpenNewProject) as useCallback; consolidated isLoading from multiple pending actions and added toast/error/git-init flows.
WorkspaceTabs layout changes
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
Reduced ADD_BUTTON_WIDTH (48→40); consolidated tab scroll into a single flex-1 container; moved CreateWorkspaceButton into a right-side shrink-0 strip with a conditional gradient fade; adjusted overflow indicators and container wrappers.
Hotkeys expansion & remap
apps/desktop/src/shared/hotkeys.ts
Added NEW_WORKSPACE (meta+n), QUICK_CREATE_WORKSPACE (meta+shift+n), and OPEN_PROJECT (meta+shift+o); remapped NEW_WINDOW from meta+shift+nmeta+alt+n.

Sequence Diagram

sequenceDiagram
    participant User
    participant Hotkeys as Hotkey system
    participant UI as CreateWorkspaceButton (DropdownMenu)
    participant Handlers as Action handlers
    participant Modal as NewWorkspaceModal
    participant Project as Project service
    participant Toast as Toast notifier

    User->>Hotkeys: press meta+n / meta+shift+n / meta+shift+o
    Hotkeys->>UI: trigger corresponding action
    UI->>Handlers: invoke modal / quick-create / open flow

    alt New Workspace (meta+n)
        Handlers->>UI: close menu
        Handlers->>Modal: open NewWorkspaceModal
        Modal-->>User: show form
    else Quick Create (meta+shift+n)
        Handlers->>UI: close menu
        Handlers->>Project: create workspace in current project
        Project-->>Handlers: success / error
        Handlers->>Toast: show result
    else Open Project (meta+shift+o)
        Handlers->>UI: close menu
        Handlers->>Project: open folder dialog (may git-init)
        Project-->>Handlers: opened / needs git / error
        Handlers->>Toast: show result / prompt
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐇 I twitch my whiskers, hop and spring,
meta+n makes new workspaces sing.
A dropdown menu, shortcuts that play,
quick-create hops and opens the way,
tabs snug right — I nibble and sway! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding keyboard shortcuts to a new workspace creation button with a dropdown menu interface redesign.
Description check ✅ Passed The description covers the key changes, includes Type of Change checkboxes, provides a test plan, and references screenshots. However, it lacks a Related Issues section linking to the PR or issue.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mental-whale-00f71c

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.

@AviPeltz AviPeltz marked this pull request as ready for review December 21, 2025 23: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: 1

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

203-203: Verify NEW_WINDOW reassignment won't disrupt existing users.

NEW_WINDOW was changed from meta+shift+n to meta+alt+n to accommodate the new QUICK_CREATE_WORKSPACE shortcut. While this resolves the conflict, it may affect users who have memorized the previous shortcut.

Consider:

  • Documenting this change in release notes or migration guide
  • Adding a temporary toast notification to inform users of the new shortcut

Would you like me to help draft a user-facing change notification?

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3ab63cc and d1c87a8.

📒 Files selected for processing (3)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx (4 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx (1 hunks)
  • apps/desktop/src/shared/hotkeys.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Avoid using any type in TypeScript - maintain type safety unless absolutely necessary

Files:

  • apps/desktop/src/shared/hotkeys.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Run Biome for formatting, linting, import organization, and safe fixes at the root level using bun run lint:fix

Files:

  • apps/desktop/src/shared/hotkeys.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
apps/desktop/**/*.{ts,tsx}

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

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
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.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/shared/hotkeys.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
**/{components,features}/**/[!.]*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Organize project structure with one folder per component: ComponentName/ComponentName.tsx with index.ts barrel export

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
**/{components,features}/**/*.{ts,tsx,test.ts,test.tsx,stories.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
**/*.{tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use React + TailwindCSS v4 + shadcn/ui for UI development

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
**/{components,features}/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

**/{components,features}/**/*.tsx: Nest components in parent's components/ folder if used only once, promote to highest shared parent's components/ if used 2+ times
Use one component per file - do not combine multiple components in a single file

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
🧠 Learnings (3)
📚 Learning: 2025-12-18T23:19:10.405Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.405Z
Learning: Applies to src/components/{ui,ai-elements,react-flow}/**/*.tsx : Use kebab-case single files for shadcn/ui components in src/components/ui/, src/components/ai-elements, and src/components/react-flow/ directories

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
📚 Learning: 2025-12-18T23:19:10.405Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.405Z
Learning: Applies to **/{components,features}/**/[!.]*.tsx : Organize project structure with one folder per component: ComponentName/ComponentName.tsx with index.ts barrel export

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
📚 Learning: 2025-12-18T23:19:10.405Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.405Z
Learning: Applies to **/*.{tsx,css} : Use React + TailwindCSS v4 + shadcn/ui for UI development

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
🧬 Code graph analysis (1)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx (2)
apps/desktop/src/shared/hotkeys.ts (1)
  • HOTKEYS (65-225)
packages/ui/src/components/ui/dropdown-menu.tsx (6)
  • DropdownMenu (249-249)
  • DropdownMenuTrigger (251-251)
  • DropdownMenuContent (252-252)
  • DropdownMenuItem (255-255)
  • DropdownMenuShortcut (260-260)
  • DropdownMenuSeparator (259-259)
🔇 Additional comments (5)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx (1)

166-211: LGTM! Clean layout simplification.

The refactor simplifies the component structure by:

  • Removing unnecessary nesting (single flex-1 container instead of three-tier wrapper)
  • Repositioning CreateWorkspaceButton outside the scroll area with shrink-0 for fixed positioning
  • Maintaining scroll fade indicators and all functional behavior

This aligns well with the dropdown menu refactor in CreateWorkspaceButton.tsx.

apps/desktop/src/shared/hotkeys.ts (1)

181-199: LGTM! Well-structured hotkey additions.

The three new workspace hotkeys are properly defined with clear descriptions and align with the dropdown menu actions in CreateWorkspaceButton.tsx.

apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx (3)

1-46: LGTM! Clean refactor to dropdown pattern.

The migration from button-based to dropdown-based UI is well-structured:

  • Proper imports for dropdown components and keyboard shortcuts
  • Derived isLoading state prevents concurrent actions
  • Local state management for dropdown open/close

48-106: LGTM! Robust action handlers with comprehensive error handling.

The three handlers are well-implemented:

  • handleModalCreate: Simple modal trigger
  • handleOpenNewProject: Handles cancellation, errors, and git-init requirements gracefully
  • handleQuickCreate: Falls back to opening new project when no current project exists

All use useCallback with correct dependencies and close the dropdown before executing actions.


108-117: LGTM! Proper keyboard shortcut integration.

The three hotkey registrations correctly:

  • Reference centralized HOTKEYS definitions
  • Guard against concurrent operations with isLoading checks
  • Use proper dependency arrays

Comment on lines +143 to +173
<DropdownMenuItem
onClick={handleModalCreate}
className="rounded-md text-[13px]"
>
<HiMiniPlus className="size-[14px] opacity-60" />
New Workspace
<DropdownMenuShortcut className="opacity-40">⌘N</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem
onClick={handleQuickCreate}
disabled={isLoading}
className="rounded-md text-[13px]"
>
<HiOutlineBolt className="size-[14px] opacity-60" />
Quick Create
<DropdownMenuShortcut className="opacity-40">
⌘⇧N
</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuSeparator className="my-1 bg-border/40" />
<DropdownMenuItem
onClick={handleOpenNewProject}
disabled={isLoading}
className="rounded-md text-[13px]"
>
<HiFolderOpen className="size-[14px] opacity-60" />
Open Project
<DropdownMenuShortcut className="opacity-40">
⌘⇧O
</DropdownMenuShortcut>
</DropdownMenuItem>
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

Use dynamic keyboard shortcuts for cross-platform support.

The dropdown menu hardcodes Mac-specific keyboard shortcut symbols (⌘N, ⌘⇧N, ⌘⇧O). This won't adapt to Windows (Ctrl+N) or Linux (Super+N) conventions.

🔎 Proposed fix using HOTKEYS.display
 <DropdownMenuItem
   onClick={handleModalCreate}
   className="rounded-md text-[13px]"
 >
   <HiMiniPlus className="size-[14px] opacity-60" />
   New Workspace
-  <DropdownMenuShortcut className="opacity-40">⌘N</DropdownMenuShortcut>
+  <DropdownMenuShortcut className="opacity-40">
+    {HOTKEYS.NEW_WORKSPACE.display.join("")}
+  </DropdownMenuShortcut>
 </DropdownMenuItem>
 <DropdownMenuItem
   onClick={handleQuickCreate}
   disabled={isLoading}
   className="rounded-md text-[13px]"
 >
   <HiOutlineBolt className="size-[14px] opacity-60" />
   Quick Create
   <DropdownMenuShortcut className="opacity-40">
-    ⌘⇧N
+    {HOTKEYS.QUICK_CREATE_WORKSPACE.display.join("")}
   </DropdownMenuShortcut>
 </DropdownMenuItem>
 <DropdownMenuSeparator className="my-1 bg-border/40" />
 <DropdownMenuItem
   onClick={handleOpenNewProject}
   disabled={isLoading}
   className="rounded-md text-[13px]"
 >
   <HiFolderOpen className="size-[14px] opacity-60" />
   Open Project
   <DropdownMenuShortcut className="opacity-40">
-    ⌘⇧O
+    {HOTKEYS.OPEN_PROJECT.display.join("")}
   </DropdownMenuShortcut>
 </DropdownMenuItem>

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
around lines 143-173, the shortcut labels are hardcoded to macOS symbols;
replace those literals with the app's hotkey display helper so shortcuts render
per-platform. Import and use the project's HOTKEYS/display utility (the same IDs
used when registering the shortcuts) instead of "⌘N", "⌘⇧N", "⌘⇧O" — e.g.
DropdownMenuShortcut children should be HOTKEYS.display('new-workspace'),
HOTKEYS.display('quick-create'), HOTKEYS.display('open-project') (or the exact
registration keys used elsewhere); ensure the HOTKEYS import path matches the
project's hotkey util and that components still receive isLoading/disabled props
unchanged.

AviPeltz and others added 2 commits December 26, 2025 23:31
- Position button absolutely at right side with gradient fade
- Increase plus icon size and match settings icon color
- Add proper padding so tabs don't hide under button

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolved conflict in CreateWorkspaceButton.tsx tooltip.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@charliecreates
Copy link
Copy Markdown
Contributor

charliecreates Bot commented Dec 27, 2025

Expand this to see my work.
  • Opened and read the updated CreateWorkspaceButton.tsx implementation to understand the new dropdown menu, shortcut-driven actions, and loading states.
  • Reviewed apps/desktop/src/shared/hotkeys.ts to confirm HOTKEYS.NEW_WORKSPACE, HOTKEYS.QUICK_CREATE_WORKSPACE, and HOTKEYS.OPEN_PROJECT definitions, display semantics, and platform-specific key handling.
  • Checked that useHotkeys registrations in CreateWorkspaceButton use the .keys values from HOTKEYS and wrap side effects (handleModalCreate, handleQuickCreate, handleOpenNewProject) in useCallback with appropriate dependency arrays for stability and correctness.
  • Scanned other useHotkeys usage in apps/desktop/src/renderer/screens/main/index.tsx and WorkspaceView/index.tsx to confirm the new button follows established dependency and guard patterns for hotkey handlers.
  • Verified the react-hotkeys-hook version (^5.2.1 in apps/desktop/package.json) to ensure the useHotkeys signature and options used in CreateWorkspaceButton match the library’s current API and behaviors.
  • Searched apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs for existing cn usage from @superset/ui/utils (e.g., SettingsTab.tsx, WorkspaceItem.tsx, BranchSwitcher.tsx) to align CreateWorkspaceButton conditional classes with current desktop patterns.
  • Searched apps/desktop/src/renderer for HotkeysProvider usage to verify that the new CreateWorkspaceButton hotkeys rely on the same global provider configuration as the rest of the desktop app and won’t conflict with existing scopes.
  • Inspected SettingsButton.tsx and its use of Tooltip + KbdGroup with HOTKEYS.SHOW_HOTKEYS.display to compare tooltip-based shortcut rendering against the new dropdown DropdownMenuItem/shortcut pattern in CreateWorkspaceButton.
  • Ran a repository search for DropdownMenuShortcut to confirm there are no existing shortcut-label components for menu items, reinforcing that CreateWorkspaceButton is effectively defining the first pattern for dropdown shortcuts in the desktop UI.
  • Inspected apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx to understand how CreateWorkspaceButton slots into the WorkspacesTabs layout, how ADD_BUTTON_WIDTH and scroll fades interact with the new button container, and how workspace navigation hotkeys (HOTKEYS.PREV_WORKSPACE, HOTKEYS.NEXT_WORKSPACE, and meta+1-9) coexist with the new creation shortcuts.

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

♻️ Duplicate comments (1)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx (1)

143-173: Use dynamic keyboard shortcuts for cross-platform support.

The dropdown menu hardcodes Mac-specific keyboard shortcut symbols (⌘N, ⌘⇧N, ⌘⇧O) on lines 149, 159, and 171. This won't adapt to Windows (Ctrl) or Linux (Super) conventions.

🔎 Proposed fix using HOTKEYS.display
 <DropdownMenuItem
   onClick={handleModalCreate}
   className="rounded-md text-[13px]"
 >
   <HiMiniPlus className="size-[14px] opacity-60" />
   New Workspace
-  <DropdownMenuShortcut className="opacity-40">⌘N</DropdownMenuShortcut>
+  <DropdownMenuShortcut className="opacity-40">
+    {HOTKEYS.NEW_WORKSPACE.display.join("")}
+  </DropdownMenuShortcut>
 </DropdownMenuItem>
 <DropdownMenuItem
   onClick={handleQuickCreate}
   disabled={isLoading}
   className="rounded-md text-[13px]"
 >
   <HiOutlineBolt className="size-[14px] opacity-60" />
   Quick Create
   <DropdownMenuShortcut className="opacity-40">
-    ⌘⇧N
+    {HOTKEYS.QUICK_CREATE_WORKSPACE.display.join("")}
   </DropdownMenuShortcut>
 </DropdownMenuItem>
 <DropdownMenuSeparator className="my-1 bg-border/40" />
 <DropdownMenuItem
   onClick={handleOpenNewProject}
   disabled={isLoading}
   className="rounded-md text-[13px]"
 >
   <HiFolderOpen className="size-[14px] opacity-60" />
   Open Project
   <DropdownMenuShortcut className="opacity-40">
-    ⌘⇧O
+    {HOTKEYS.OPEN_PROJECT.display.join("")}
   </DropdownMenuShortcut>
 </DropdownMenuItem>
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1c87a8 and d40d9b0.

📒 Files selected for processing (3)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
  • apps/desktop/src/shared/hotkeys.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Avoid using any type in TypeScript - maintain type safety unless absolutely necessary

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/shared/hotkeys.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Run Biome for formatting, linting, import organization, and safe fixes at the root level using bun run lint:fix

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/shared/hotkeys.ts
**/{components,features}/**/[!.]*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Organize project structure with one folder per component: ComponentName/ComponentName.tsx with index.ts barrel export

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
**/{components,features}/**/*.{ts,tsx,test.ts,test.tsx,stories.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
apps/desktop/src/{main,renderer,preload}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
**/*.{tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use React + TailwindCSS v4 + shadcn/ui for UI development

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
**/{components,features}/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

**/{components,features}/**/*.tsx: Nest components in parent's components/ folder if used only once, promote to highest shared parent's components/ if used 2+ times
Use one component per file - do not combine multiple components in a single file

Files:

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

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

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
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.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
  • apps/desktop/src/shared/hotkeys.ts
🧠 Learnings (2)
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to src/components/{ui,ai-elements,react-flow}/**/*.tsx : Use kebab-case single files for shadcn/ui components in src/components/ui/, src/components/ai-elements, and src/components/react-flow/ directories

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to **/*.{tsx,css} : Use React + TailwindCSS v4 + shadcn/ui for UI development

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx
🧬 Code graph analysis (1)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx (4)
packages/ui/src/components/ui/sonner.tsx (1)
  • toast (40-40)
apps/desktop/src/shared/hotkeys.ts (1)
  • HOTKEYS (65-237)
packages/ui/src/components/ui/dropdown-menu.tsx (6)
  • DropdownMenu (249-249)
  • DropdownMenuTrigger (251-251)
  • DropdownMenuContent (252-252)
  • DropdownMenuItem (255-255)
  • DropdownMenuShortcut (260-260)
  • DropdownMenuSeparator (259-259)
packages/ui/src/components/ui/tooltip.tsx (3)
  • Tooltip (76-76)
  • TooltipTrigger (76-76)
  • TooltipContent (76-76)
⏰ 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 (9)
apps/desktop/src/shared/hotkeys.ts (2)

193-211: LGTM! Well-structured hotkey definitions.

The three new workspace-related hotkeys are well-defined with clear labels, categories, and descriptions. They follow the existing pattern and integrate cleanly with the hotkey system.


215-215: Verify historical change claim for NEW_WINDOW shortcut.

The review states NEW_WINDOW changed from meta+shift+n to meta+alt+n, but git history does not support this. In commit d40d9b0 (which introduced QUICK_CREATE_WORKSPACE), NEW_WINDOW already uses meta+alt+n. QUICK_CREATE_WORKSPACE was assigned meta+shift+n, not NEW_WINDOW. No evidence exists showing NEW_WINDOW previously used meta+shift+n. Additionally, no documentation or release notes mention this change.

apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsx (7)

1-21: LGTM! Appropriate imports for the refactor.

All imports are correctly sourced for the DropdownMenu-based UI and hotkey integration.


30-30: Good state management for dropdown control.

Using local state for the dropdown open/closed state is appropriate for this UI interaction.


43-46: Well-consolidated loading state.

Deriving isLoading from all async operations ensures consistent disabled state across the dropdown menu.


48-51: Clean modal trigger handler.

The callback properly closes the dropdown before opening the modal.


53-89: Excellent error handling in handleOpenNewProject.

The function properly handles:

  • Canceled operations
  • Error results with user-friendly messages
  • Git initialization requirements
  • Success cases with toast notifications

The error boundaries are well-defined and provide clear user feedback.


91-106: Good fallback logic in handleQuickCreate.

The function appropriately delegates to handleOpenNewProject when no current project exists, providing a smooth UX.


119-142: Well-structured DropdownMenu UI.

The dropdown trigger and tooltip provide good accessibility with clear labels and visual feedback. The styling is consistent with the design system.

@charliecreates
Copy link
Copy Markdown
Contributor

Nice UX improvement overall — the dropdown consolidates the “new workspace” actions cleanly, and the right-pinned button + fade treatment in WorkspacesTabs reads well.

A few things I’d address before merging:

  • CreateWorkspaceButton can render "undefined" in the class attribute
    In CreateWorkspaceButton.tsx (around line 128), className={${className} flex ...} will produce "undefined flex ..." when className isn’t passed. This is easy to miss but ends up in the DOM.
    Suggest using the existing pattern from neighboring components (cn from @superset/ui/utils), e.g. className={cn(className, "flex ...")}.

  • Don’t hardcode Mac-only shortcut glyphs in the dropdown
    In CreateWorkspaceButton.tsx (lines ~149–172), the shortcuts are hardcoded as ⌘N, ⌘⇧N, ⌘⇧O. Since you already have HOTKEYS.*.display (and platform-aware formatting) in shared/hotkeys.ts, it’d be better to render from there so:

    1. the UI stays correct on Windows/Linux, and
    2. future key remaps don’t require touching this component.
      Even if DropdownMenuShortcut wants a single node, you could render a KbdGroup like SettingsButton does, or join display with a platform-appropriate separator.
  • Hotkey behavior vs browser/Electron defaults (and the NEW_WINDOW remap)
    In shared/hotkeys.ts (lines ~193–218), NEW_WINDOW moved from meta+shift+n to meta+alt+n to free up meta+shift+n. That’s fine technically, but it’s a pretty “muscle memory” heavy shortcut. If this ships, it likely needs a quick note in release notes / changelog UI.
    Also, meta+n is a very common “New…” accelerator. If Electron menu accelerators also bind this, you may get double-triggering unless defaults are prevented. Consider using useHotkeys(..., { preventDefault: true }, deps) (or otherwise ensure the default isn’t firing).

  • Trigger disabling is slightly inconsistent with the menu content + hotkey
    The trigger button is disabled on isLoading, but “New Workspace” itself isn’t disabled (and ⌘N still works even when the trigger is disabled). If the goal is “no concurrent async operations,” I’d either:

    1. disable ⌘N/handleModalCreate when isLoading, or
    2. keep the trigger enabled and only disable the menu items that actually start async work.
  • WorkspacesTabs: keep the “reserved space” in sync
    ADD_BUTTON_WIDTH = 40 is used in width calculations, but the visual reservation is currently pr-10 plus the right overlay container padding. It works as-is, but it’s a bit brittle — if the button sizing changes again, it’s easy to update one and forget the other. A small comment or a single source of truth (constant → style/padding) would help.

If you want, I can suggest a concrete rendering approach for DropdownMenuShortcut that uses HOTKEYS.*.display while keeping the menu layout tight and consistent with the rest of the app.

- Extract handlers to useCallback for proper memoization
- Remove incorrect dependency arrays from useHotkeys calls
- Fix createBranchWorkspace dependency in useEffect

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

Co-Authored-By: Claude Opus 4.5 <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

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60f538b and 9a4fd5d.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Avoid using any type in TypeScript - maintain type safety unless absolutely necessary

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

Run Biome for formatting, linting, import organization, and safe fixes at the root level using bun run lint:fix

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
**/{components,features}/**/[!.]*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Organize project structure with one folder per component: ComponentName/ComponentName.tsx with index.ts barrel export

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
**/{components,features}/**/*.{ts,tsx,test.ts,test.tsx,stories.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

Use React + TailwindCSS v4 + shadcn/ui for UI development

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

**/{components,features}/**/*.tsx: Nest components in parent's components/ folder if used only once, promote to highest shared parent's components/ if used 2+ times
Use one component per file - do not combine multiple components in a single file

Files:

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

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

apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc
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.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from @trpc/server/observable instead of async generators, as the library explicitly checks isObservable(result) and throws an error otherwise

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to **/*.{tsx,css} : Use React + TailwindCSS v4 + shadcn/ui for UI development

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to src/components/{ui,ai-elements,react-flow}/**/*.tsx : Use kebab-case single files for shadcn/ui components in src/components/ui/, src/components/ai-elements, and src/components/react-flow/ directories

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
⏰ 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 (7)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx (7)

1-1: LGTM: useCallback import added for proper memoization.

The addition of useCallback supports the handler extraction pattern used later in the file.


19-19: LGTM: Button width adjustment.

The reduction from 48 to 40 pixels aligns with the UI redesign described in the PR objectives.


77-77: LGTM: Correct dependency for react-query mutation.

Including createBranchWorkspace in the dependency array is the correct pattern for react-query mutations, ensuring the effect has access to the current mutation object.


88-99: LGTM: Excellent refactoring with proper memoization.

Extracting the workspace switch handler to useCallback with correct dependencies improves performance and follows React best practices.


101-119: LGTM: Navigation handlers properly memoized.

Both handlePrevWorkspace and handleNextWorkspace are correctly implemented with complete dependency arrays.


121-123: LGTM: Hotkeys correctly wired to memoized handlers.

The useHotkeys calls properly reference the memoized handlers and centralized hotkey definitions from shared/hotkeys.ts.


168-203: LGTM: Layout refactoring supports new fixed button design.

The restructured layout correctly implements the scrollable tabs area with appropriate padding for the right-side button container. The pr-10 padding accommodates the absolutely positioned right-side elements.

Comment on lines +206 to 220
{showStartFade && (
<div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-linear-to-r from-background to-transparent" />
)}

{/* Right side: gradient fade + button container */}
<div className="absolute right-0 top-0 h-full flex items-center pointer-events-none">
{/* Gradient fade - only show when content overflows */}
{showEndFade && (
<div className="pointer-events-none absolute right-0 top-0 h-full w-8 bg-linear-to-l from-background to-transparent" />
<div className="h-full w-8 bg-linear-to-l from-background to-transparent" />
)}
{/* Button with solid background */}
<div className="h-full flex items-center bg-background pl-1 pr-2 pointer-events-auto">
<CreateWorkspaceButton className="no-drag" />
</div>
</div>
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 | 🔴 Critical

Fix invalid TailwindCSS gradient class names.

Lines 207 and 214 use bg-linear-to-r and bg-linear-to-l, which are not valid TailwindCSS classes. The correct syntax for gradients in TailwindCSS (including v4) is bg-gradient-to-r and bg-gradient-to-l.

🔎 Proposed fix for gradient class names
 {/* Left fade for scroll indication */}
 {showStartFade && (
-  <div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-linear-to-r from-background to-transparent" />
+  <div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-gradient-to-r from-background to-transparent" />
 )}

 {/* Right side: gradient fade + button container */}
 <div className="absolute right-0 top-0 h-full flex items-center pointer-events-none">
   {/* Gradient fade - only show when content overflows */}
   {showEndFade && (
-    <div className="h-full w-8 bg-linear-to-l from-background to-transparent" />
+    <div className="h-full w-8 bg-gradient-to-l from-background to-transparent" />
   )}
   {/* Button with solid background */}
   <div className="h-full flex items-center bg-background pl-1 pr-2 pointer-events-auto">
     <CreateWorkspaceButton className="no-drag" />
   </div>
 </div>
📝 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
{showStartFade && (
<div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-linear-to-r from-background to-transparent" />
)}
{/* Right side: gradient fade + button container */}
<div className="absolute right-0 top-0 h-full flex items-center pointer-events-none">
{/* Gradient fade - only show when content overflows */}
{showEndFade && (
<div className="pointer-events-none absolute right-0 top-0 h-full w-8 bg-linear-to-l from-background to-transparent" />
<div className="h-full w-8 bg-linear-to-l from-background to-transparent" />
)}
{/* Button with solid background */}
<div className="h-full flex items-center bg-background pl-1 pr-2 pointer-events-auto">
<CreateWorkspaceButton className="no-drag" />
</div>
</div>
{showStartFade && (
<div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-gradient-to-r from-background to-transparent" />
)}
{/* Right side: gradient fade + button container */}
<div className="absolute right-0 top-0 h-full flex items-center pointer-events-none">
{/* Gradient fade - only show when content overflows */}
{showEndFade && (
<div className="h-full w-8 bg-gradient-to-l from-background to-transparent" />
)}
{/* Button with solid background */}
<div className="h-full flex items-center bg-background pl-1 pr-2 pointer-events-auto">
<CreateWorkspaceButton className="no-drag" />
</div>
</div>
🤖 Prompt for AI Agents
In
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx
around lines 206 to 220, the gradient class names are incorrect (bg-linear-to-r
and bg-linear-to-l). Replace those with the correct TailwindCSS gradient utility
names bg-gradient-to-r and bg-gradient-to-l respectively, ensuring other
gradient-related classes (from-... to-...) remain unchanged so the fades render
correctly.

@AviPeltz AviPeltz merged commit 3414a49 into main Dec 27, 2025
5 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

Service Status
Neon Database (Neon)

Thank you for your contribution! 🎉


Preview resources have been processed for cleanup

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