Skip to content

feat(desktop): improve StartView onboarding CTA design#930

Merged
saddlepaddle merged 4 commits into
mainfrom
onboarding
Jan 24, 2026
Merged

feat(desktop): improve StartView onboarding CTA design#930
saddlepaddle merged 4 commits into
mainfrom
onboarding

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Jan 24, 2026

Summary

  • Simplify StartView layout with cleaner visual hierarchy
  • Use proper shadcn typography (h4) for "Open a Project" heading
  • Remove Clone from GitHub secondary option
  • Larger dropzone with dashed border and card background
  • Folder icon with gradient background treatment for visual interest
  • Update CTA text to "Drag and drop a git folder to open"
  • Remove loading animation for simpler UX
  • Add subtle color transition on drag state change

Test plan

  • Open the app without any projects
  • Verify the StartView displays correctly with new design
  • Test drag and drop a git folder onto the dropzone
  • Verify color transition on drag over
  • Click the dropzone to open file picker
  • Verify error states still display correctly

Summary by CodeRabbit

  • New Features

    • Added a project dashboard for creating workspaces with base branch selection and branch auto-generation from workspace titles.
    • Implemented drag-and-drop support for opening projects directly from Git repository folders.
  • Improvements

    • Enhanced workspace creation workflow with branch search functionality and automatic branch naming.
    • Simplified project opening experience with streamlined UI and improved error messaging.
    • Added visual indicators for default branches and destructive actions.

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

- 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
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 24, 2026

📝 Walkthrough

Walkthrough

A 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

Cohort / File(s) Summary
Project Dashboard Route
apps/desktop/src/renderer/routes/_authenticated/_dashboard/project/$projectId/page.tsx
New page component (+322 lines) implementing workspace creation with branch selection. Includes TRPC-based project/branch data fetching, branch name auto-generation, popover-based branch picker with search, keyboard shortcuts for form submission, and toast notifications for success/error states.
Startup View Refactoring
apps/desktop/src/renderer/screens/main/components/StartView/index.tsx
apps/desktop/src/renderer/screens/main/components/StartView/StartTopBar.tsx
Replaced recent projects UI with drag-and-drop project opening workflow (+201/-183, +6/-17 lines). StartView now accepts folders with .git directory via drag-and-drop, provides dynamic visual feedback, and navigates to project route on successful open. StartTopBar simplified to conditionally render window controls only.
Sidebar Navigation Updates
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/*
Minor updates across sidebar components. SidebarDropZone now navigates to project route instead of creating workspace directly (+9/-17). ProjectHeader icon styling enhanced with destructive color class (+8/-2). WorkspaceSidebar placeholder text updated (+1/-1).

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
Loading
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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A new dashboard hops into view,
With branches to pick and workspaces brew,
Drag folders in—no need to confuse—
The startup screen's got a bold drag-and-drop use! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: improving the StartView onboarding CTA design with cleaner visual hierarchy, updated dropzone styling, and simplified UX.
Description check ✅ Passed The description includes a clear summary of changes and a comprehensive test plan, covering the main modifications to the StartView component layout and styling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 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 to handleOpenProject (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 handleOpenResult in both handleOpenProject and handleDrop.

Comment on lines +183 to +193
<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>
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

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.

Suggested change
<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).

@saddlepaddle saddlepaddle merged commit 40e6618 into main Jan 24, 2026
5 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

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