feat(desktop): improve StartView onboarding CTA design#930
Conversation
- Simplify layout with cleaner hierarchy - Use proper shadcn typography for headings - Remove Clone from GitHub option - Larger dropzone with dashed border and bg-card - Add folder icon with gradient background treatment - Update CTA text to "Drag and drop a git folder to open" - Remove loading animation in favor of simpler UX - Add subtle transition on drag state change
📝 WalkthroughWalkthroughA new project dashboard page with workspace creation workflow is introduced alongside UI refactoring in the startup view to support drag-and-drop project opening. Navigation logic is updated across sidebar components to route to the new project page. The startup view transitions from a recent projects list to a drag-and-drop entry point. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ProjectPage as ProjectPage<br/>(New Route)
participant TRPC
participant Database
participant UI as Form UI<br/>(Branch Picker)
User->>ProjectPage: Navigate to /$projectId/
ProjectPage->>TRPC: Loader: fetchProject($projectId)
TRPC->>Database: Query project & branches
Database-->>TRPC: Project data
TRPC-->>ProjectPage: Preloaded data
User->>UI: Enter workspace title
UI->>UI: generateBranchFromTitle(title)
User->>UI: Click "Advanced" to change branch
UI->>UI: Open branch picker popover
User->>UI: Search/select base branch
UI->>UI: Update baseBranch state
User->>ProjectPage: Press Enter or click Create
ProjectPage->>TRPC: createWorkspace(title, baseBranch)
TRPC->>Database: Create workspace
Database-->>TRPC: Success
TRPC-->>ProjectPage: Workspace created
ProjectPage->>UI: Show success toast
sequenceDiagram
participant User
participant StartView
participant FileSystem as File System
participant useOpenFromPath
participant Router
participant ProjectPage as Project Route
User->>StartView: Drag folder over drop zone
StartView->>StartView: onDragOver: Set dragActive=true
StartView->>UI: Highlight drop zone
User->>StartView: Drop folder
StartView->>StartView: onDrop: Extract dropped path
StartView->>FileSystem: Verify .git directory exists
FileSystem-->>StartView: .git found
StartView->>useOpenFromPath: Call with folder path
useOpenFromPath->>FileSystem: Initialize/validate project
FileSystem-->>useOpenFromPath: Project metadata (projectId)
useOpenFromPath-->>StartView: Success with projectId
StartView->>Router: navigate(/project/$projectId)
Router->>ProjectPage: Load project dashboard
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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
🤖 Fix all issues with AI agents
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/project/`$projectId/page.tsx:
- Around line 183-193: The UI currently renders "from null" when
effectiveBaseBranch is null; update the rendering in the paragraph that uses
effectiveBaseBranch (the span following generateBranchFromTitle and GoGitBranch)
to use a safe fallback or conditional display—e.g., show "from
{effectiveBaseBranch ?? 'base-branch'}" or omit the "from" span while branches
are loading—so that the UI never displays "null" (touch the span that references
effectiveBaseBranch in the component containing generateBranchFromTitle and
GoGitBranch).
🧹 Nitpick comments (1)
apps/desktop/src/renderer/screens/main/components/StartView/index.tsx (1)
106-169: Consider extracting shared success handler to reduce duplication.The success handling logic in
handleDrop(lines 136-160) is nearly identical tohandleOpenProject(lines 47-71). While not critical, extracting a shared handler would improve maintainability.♻️ Suggested refactor
+ const handleOpenResult = useCallback( + (result: Awaited<ReturnType<typeof openNew.mutateAsync>>) => { + if ("canceled" in result && result.canceled) return; + + if ("error" in result) { + setError(result.error); + return; + } + + if ("needsGitInit" in result) { + setInitGitDialog({ + isOpen: true, + selectedPath: result.selectedPath, + }); + return; + } + + if ("project" in result && result.project) { + navigate({ + to: "/project/$projectId", + params: { projectId: result.project.id }, + }); + } + }, + [navigate], + ); const handleOpenProject = () => { setError(null); openNew.mutate(undefined, { - onSuccess: (result) => { - // ... duplicated logic - }, + onSuccess: handleOpenResult, onError: (err) => { setError(err.message || "Failed to open project"); }, }); };Then use
handleOpenResultin bothhandleOpenProjectandhandleDrop.
| <p | ||
| className={`text-sm text-muted-foreground flex items-center gap-2 transition-opacity ${title ? "opacity-100" : "opacity-0"}`} | ||
| > | ||
| <GoGitBranch className="size-3.5" /> | ||
| <span className="font-mono"> | ||
| {generateBranchFromTitle(title) || "branch-name"} | ||
| </span> | ||
| <span className="text-muted-foreground/50"> | ||
| from {effectiveBaseBranch} | ||
| </span> | ||
| </p> |
There was a problem hiding this comment.
Handle null effectiveBaseBranch in display text.
When branches are loading or fail to load, effectiveBaseBranch could be null, rendering "from null" in the UI.
🐛 Proposed fix
<span className="text-muted-foreground/50">
- from {effectiveBaseBranch}
+ from {effectiveBaseBranch ?? "..."}
</span>📝 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.
| <p | |
| className={`text-sm text-muted-foreground flex items-center gap-2 transition-opacity ${title ? "opacity-100" : "opacity-0"}`} | |
| > | |
| <GoGitBranch className="size-3.5" /> | |
| <span className="font-mono"> | |
| {generateBranchFromTitle(title) || "branch-name"} | |
| </span> | |
| <span className="text-muted-foreground/50"> | |
| from {effectiveBaseBranch} | |
| </span> | |
| </p> | |
| <p | |
| className={`text-sm text-muted-foreground flex items-center gap-2 transition-opacity ${title ? "opacity-100" : "opacity-0"}`} | |
| > | |
| <GoGitBranch className="size-3.5" /> | |
| <span className="font-mono"> | |
| {generateBranchFromTitle(title) || "branch-name"} | |
| </span> | |
| <span className="text-muted-foreground/50"> | |
| from {effectiveBaseBranch ?? "..."} | |
| </span> | |
| </p> |
🤖 Prompt for AI Agents
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/project/`$projectId/page.tsx
around lines 183 - 193, The UI currently renders "from null" when
effectiveBaseBranch is null; update the rendering in the paragraph that uses
effectiveBaseBranch (the span following generateBranchFromTitle and GoGitBranch)
to use a safe fallback or conditional display—e.g., show "from
{effectiveBaseBranch ?? 'base-branch'}" or omit the "from" span while branches
are loading—so that the UI never displays "null" (touch the span that references
effectiveBaseBranch in the component containing generateBranchFromTitle and
GoGitBranch).
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
Summary
Test plan
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.