project panel: Add git clone action to empty state (#36371)

Danilo Leal created

This PR adds the git clone action to the project panel. It also changes
the "open" button to open a folder instead of the recent projects modal,
which feels faster to start with, more intuitive, and also consistent
with VS Code (which I think is good in this specific case).

<img width="500" height="1334" alt="CleanShot 2025-08-17 at 2  10 01@2x"
src="https://github.com/user-attachments/assets/ff953228-9e8e-413b-89ba-fa0870a0df17"
/>

Release Notes:

- Improved the project panel empty state by including the git clone
action and allowing users to quickly open a local folder.

Change summary

crates/onboarding/src/welcome.rs          |  2 
crates/project_panel/src/project_panel.rs | 41 +++++++++++++++++++-----
2 files changed, 33 insertions(+), 10 deletions(-)

Detailed changes

crates/onboarding/src/welcome.rs 🔗

@@ -37,7 +37,7 @@ const CONTENT: (Section<4>, Section<3>) = (
             },
             SectionEntry {
                 icon: IconName::CloudDownload,
-                title: "Clone a Repo",
+                title: "Clone Repository",
                 action: &git::Clone,
             },
             SectionEntry {

crates/project_panel/src/project_panel.rs 🔗

@@ -57,9 +57,9 @@ use std::{
 };
 use theme::ThemeSettings;
 use ui::{
-    Color, ContextMenu, DecoratedIcon, Icon, IconDecoration, IconDecorationKind, IndentGuideColors,
-    IndentGuideLayout, KeyBinding, Label, LabelSize, ListItem, ListItemSpacing, ScrollableHandle,
-    Scrollbar, ScrollbarState, StickyCandidate, Tooltip, prelude::*, v_flex,
+    Color, ContextMenu, DecoratedIcon, Divider, Icon, IconDecoration, IconDecorationKind,
+    IndentGuideColors, IndentGuideLayout, KeyBinding, Label, LabelSize, ListItem, ListItemSpacing,
+    ScrollableHandle, Scrollbar, ScrollbarState, StickyCandidate, Tooltip, prelude::*, v_flex,
 };
 use util::{ResultExt, TakeUntilExt, TryFutureExt, maybe, paths::compare_paths};
 use workspace::{
@@ -69,7 +69,6 @@ use workspace::{
     notifications::{DetachAndPromptErr, NotifyTaskExt},
 };
 use worktree::CreatedEntry;
-use zed_actions::OpenRecent;
 
 const PROJECT_PANEL_KEY: &str = "ProjectPanel";
 const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX;
@@ -5521,24 +5520,48 @@ impl Render for ProjectPanel {
                     .with_priority(3)
                 }))
         } else {
+            let focus_handle = self.focus_handle(cx).clone();
+
             v_flex()
                 .id("empty-project_panel")
-                .size_full()
                 .p_4()
+                .size_full()
+                .items_center()
+                .justify_center()
+                .gap_1()
                 .track_focus(&self.focus_handle(cx))
                 .child(
-                    Button::new("open_project", "Open a project")
+                    Button::new("open_project", "Open Project")
                         .full_width()
                         .key_binding(KeyBinding::for_action_in(
-                            &OpenRecent::default(),
-                            &self.focus_handle,
+                            &workspace::Open,
+                            &focus_handle,
                             window,
                             cx,
                         ))
                         .on_click(cx.listener(|this, _, window, cx| {
                             this.workspace
                                 .update(cx, |_, cx| {
-                                    window.dispatch_action(OpenRecent::default().boxed_clone(), cx);
+                                    window.dispatch_action(workspace::Open.boxed_clone(), cx);
+                                })
+                                .log_err();
+                        })),
+                )
+                .child(
+                    h_flex()
+                        .w_1_2()
+                        .gap_2()
+                        .child(Divider::horizontal())
+                        .child(Label::new("or").size(LabelSize::XSmall).color(Color::Muted))
+                        .child(Divider::horizontal()),
+                )
+                .child(
+                    Button::new("clone_repo", "Clone Repository")
+                        .full_width()
+                        .on_click(cx.listener(|this, _, window, cx| {
+                            this.workspace
+                                .update(cx, |_, cx| {
+                                    window.dispatch_action(git::Clone.boxed_clone(), cx);
                                 })
                                 .log_err();
                         })),