Conversation
Replace the dropdown menu for "more options" workspace creation with a modal dialog. The split button UI remains the same - plus button for quick create, chevron opens the new modal for project selection. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update the new workspace modal to show project selection with optional title and branch name fields in a single view. Users can: - Select/reselect a project from the list - Optionally provide a title (becomes workspace name) - Optionally provide a custom branch name (auto-generated from title) Backend now accepts branchName parameter in workspace creation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove "Other projects" subsection, show all projects in flat list - Current project sorted to top automatically - Increase modal height (min-h-[500px]) - Increase project list scroll area (max-h-64) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove subtitle description
- Remove path display under project names
- Remove borders from project items (simple list style)
- Remove "(optional)" text from labels
- Remove helper text under branch field
- Narrower modal (max-w-sm)
- Shorter button text ("Create", "Browse...")
- Tighter spacing throughout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WalkthroughThis change implements a new workspace creation modal. The TRPC workspaces.create procedure accepts an optional branchName field. A new NewWorkspaceModal component provides UI for selecting a project, workspace name, and git branch. WorkspaceDropdown is refactored to trigger the modal instead of using a dropdown menu, with state managed via a new Zustand store. Changes
Sequence DiagramsequenceDiagram
actor User
participant Modal as NewWorkspaceModal
participant Store as Modal Store
participant TRPC as TRPC Backend
participant API as Workspace API
User->>Modal: Open modal / Mount component
activate Modal
Note over Modal: Auto-select current<br/>project if available
Modal->>TRPC: Query active workspace<br/>& recent projects
TRPC-->>Modal: Return projects
User->>Modal: Select project
User->>Modal: Enter workspace title
Note over Modal: Auto-generate branch<br/>from title (unless edited)
User->>Modal: Click Create Workspace
Modal->>Store: Update internal state
Store-->>Modal: State updated
Modal->>TRPC: Call create mutation<br/>(projectId, name, branchName)
activate TRPC
TRPC->>API: Create workspace
API-->>TRPC: Workspace created
TRPC-->>Modal: Return result
deactivate TRPC
Note over Modal: Show success toast
Modal->>Store: closeModal()
Store-->>Modal: Modal closed
deactivate Modal
User->>User: Navigate to workspace
Estimated Code review effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes Key areas requiring attention:
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings, 1 inconclusive)
✨ 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: 0
🧹 Nitpick comments (1)
apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx (1)
32-43: Consider edge case handling in branch name generation.The
generateBranchFromTitlefunction handles most common cases well, but may produce unexpected results for certain edge cases:
- Multiple consecutive spaces/hyphens are collapsed, which is good
- Leading/trailing hyphens are removed
- However, titles with only special characters would result in an empty string
Consider adding a fallback or validation to ensure the generated branch name is never empty when a title is provided:
function generateBranchFromTitle(title: string): string { if (!title.trim()) return ""; - return title + const branch = title .toLowerCase() .trim() .replace(/[^a-z0-9\s-]/g, "") .replace(/\s+/g, "-") .replace(/-+/g, "-") .replace(/^-|-$/g, "") .slice(0, 50); + + // Return empty if no valid characters remain (e.g., title was all special chars) + return branch || ""; }Note: The current implementation already returns empty string correctly, so this is just for clarity and maintainability.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts(2 hunks)apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx(1 hunks)apps/desktop/src/renderer/components/NewWorkspaceModal/index.ts(1 hunks)apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsx(4 hunks)apps/desktop/src/renderer/screens/main/index.tsx(2 hunks)apps/desktop/src/renderer/stores/new-workspace-modal.ts(1 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/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/renderer/components/NewWorkspaceModal/index.tsapps/desktop/src/renderer/stores/new-workspace-modal.tsapps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsxapps/desktop/src/renderer/screens/main/index.tsx
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: Please use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary
Files:
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/renderer/components/NewWorkspaceModal/index.tsapps/desktop/src/renderer/stores/new-workspace-modal.tsapps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsxapps/desktop/src/renderer/screens/main/index.tsx
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Biome for code formatting and linting, running at root level for speed
Files:
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/renderer/components/NewWorkspaceModal/index.tsapps/desktop/src/renderer/stores/new-workspace-modal.tsapps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsxapps/desktop/src/renderer/screens/main/index.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid
anytype and prioritize type safety in TypeScript code
Files:
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/renderer/components/NewWorkspaceModal/index.tsapps/desktop/src/renderer/stores/new-workspace-modal.tsapps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsxapps/desktop/src/renderer/screens/main/index.tsx
**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/components/**/*.{ts,tsx}: Structure project folders as one folder per component with PascalCase naming (ComponentName/ComponentName.tsx + index.ts barrel export)
Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Use one component per file (no multi-component files)
Files:
apps/desktop/src/renderer/components/NewWorkspaceModal/index.tsapps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Call IPC methods from renderer process using window.ipcRenderer.invoke with type-safe object parameters
Files:
apps/desktop/src/renderer/components/NewWorkspaceModal/index.tsapps/desktop/src/renderer/stores/new-workspace-modal.tsapps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsxapps/desktop/src/renderer/screens/main/index.tsx
🧠 Learnings (1)
📚 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/stores/new-workspace-modal.ts
🧬 Code graph analysis (2)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (1)
apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts (1)
generateBranchName(120-130)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsx (3)
apps/desktop/src/renderer/react-query/workspaces/useCreateWorkspace.ts (1)
useCreateWorkspace(12-61)apps/desktop/src/renderer/react-query/projects/useOpenNew.ts (1)
useOpenNew(7-22)apps/desktop/src/renderer/stores/new-workspace-modal.ts (1)
useOpenNewWorkspaceModal(30-31)
⏰ 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). (6)
- GitHub Check: Deploy API
- GitHub Check: Deploy Web
- GitHub Check: Deploy Marketing
- GitHub Check: Deploy Docs
- GitHub Check: Deploy Admin
- GitHub Check: Build
🔇 Additional comments (7)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (1)
33-33: LGTM! Clean support for optional branch names.The addition of the optional
branchNamefield and the fallback logic usingtrim()to prevent empty strings is well-implemented. This aligns nicely with the new modal-based workflow.Also applies to: 42-42
apps/desktop/src/renderer/stores/new-workspace-modal.ts (1)
1-33: LGTM! Well-structured Zustand store.The modal state management is clean and follows the coding guidelines for preferring Zustand. The convenience hooks provide optimized selectors for consumers.
Based on coding guidelines: Prefers Zustand for state management as instructed.
apps/desktop/src/renderer/components/NewWorkspaceModal/index.ts (1)
1-1: LGTM! Proper barrel export.The index barrel follows the component structure guidelines correctly.
Based on coding guidelines: Follows the pattern of ComponentName/ComponentName.tsx + index.ts barrel export.
apps/desktop/src/renderer/screens/main/index.tsx (1)
9-9: LGTM! Clean modal integration.The NewWorkspaceModal is properly integrated into the main screen alongside existing modals.
Also applies to: 301-301
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceDropdown.tsx (1)
5-5: LGTM! Effective simplification of workspace creation flow.The refactor from a complex dropdown menu to a split button with modal integration significantly reduces complexity. The primary action creates a workspace in the current project (or opens a new project if none exists), while the chevron opens the full modal for more options. The ref blur pattern and toast promises are used appropriately.
Also applies to: 18-18, 24-24, 30-86, 112-128
apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx (2)
76-87: useEffect usage is justified for UX requirements.While the coding guidelines suggest avoiding effects unless necessary, both effects here serve clear UX purposes:
- Auto-selecting the current project when the modal opens
- Auto-generating branch names from the title (unless manually edited)
These effects are appropriate for this component's functionality.
Based on coding guidelines: Effects are used sparingly and only where necessary for the UX flow.
45-263: Well-structured modal component with good error handling.The component is cleanly organized with:
- Clear state management for form inputs
- Proper integration with TRPC mutations
- Comprehensive error handling for various edge cases (canceled, error, needsGitInit)
- User-friendly error messages with actionable guidance
- Clean separation of concerns between handlers and rendering
The branchNameEdited flag pattern effectively tracks user intent for auto-generation behavior.
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
Description
Related Issues
Type of Change
Testing
Screenshots (if applicable)
Additional Notes
Summary by CodeRabbit
New Features
UI/UX Changes
✏️ Tip: You can customize this high-level summary in your review settings.