ui(desktop): new button with shortcuts option#460
Conversation
📝 WalkthroughWalkthroughReplaces 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
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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_WINDOWwas changed frommeta+shift+ntometa+alt+nto accommodate the newQUICK_CREATE_WORKSPACEshortcut. 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
📒 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.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsxapps/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.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsxapps/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 insrc/lib/trpc
Use alias as defined intsconfig.jsonwhen 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/observableinstead of async generators, as the library explicitly checksisObservable(result)and throws an error otherwise
Files:
apps/desktop/src/shared/hotkeys.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/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-1container instead of three-tier wrapper)- Repositioning
CreateWorkspaceButtonoutside the scroll area withshrink-0for 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
isLoadingstate 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 triggerhandleOpenNewProject: Handles cancellation, errors, and git-init requirements gracefullyhandleQuickCreate: Falls back to opening new project when no current project existsAll use
useCallbackwith correct dependencies and close the dropdown before executing actions.
108-117: LGTM! Proper keyboard shortcut integration.The three hotkey registrations correctly:
- Reference centralized
HOTKEYSdefinitions- Guard against concurrent operations with
isLoadingchecks- Use proper dependency arrays
| <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> |
There was a problem hiding this comment.
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.
- 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>
Expand this to see my work.
|
There was a problem hiding this comment.
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
📒 Files selected for processing (3)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsxapps/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.tsxapps/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.tsxapps/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 insrc/lib/trpc
Use alias as defined intsconfig.jsonwhen 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/observableinstead of async generators, as the library explicitly checksisObservable(result)and throws an error otherwise
Files:
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/CreateWorkspaceButton.tsxapps/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+ntometa+alt+n, but git history does not support this. In commit d40d9b0 (which introduced QUICK_CREATE_WORKSPACE), NEW_WINDOW already usesmeta+alt+n. QUICK_CREATE_WORKSPACE was assignedmeta+shift+n, not NEW_WINDOW. No evidence exists showing NEW_WINDOW previously usedmeta+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
isLoadingfrom 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
handleOpenNewProjectwhen 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.
|
Nice UX improvement overall — the dropdown consolidates the “new workspace” actions cleanly, and the right-pinned button + fade treatment in A few things I’d address before merging:
If you want, I can suggest a concrete rendering approach for |
- 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>
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 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 insrc/lib/trpc
Use alias as defined intsconfig.jsonwhen 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/observableinstead of async generators, as the library explicitly checksisObservable(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
useCallbacksupports 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
createBranchWorkspacein 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
useCallbackwith correct dependencies improves performance and follows React best practices.
101-119: LGTM: Navigation handlers properly memoized.Both
handlePrevWorkspaceandhandleNextWorkspaceare correctly implemented with complete dependency arrays.
121-123: LGTM: Hotkeys correctly wired to memoized handlers.The
useHotkeyscalls properly reference the memoized handlers and centralized hotkey definitions fromshared/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-10padding accommodates the absolutely positioned right-side elements.
| {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> |
There was a problem hiding this comment.
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.
| {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.
Summary
Type of Change
Test plan
Screenshots
Screen.Recording.2025-12-21.at.2.54.15.PM.mov
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
UI/UX Improvements
✏️ Tip: You can customize this high-level summary in your review settings.