git_ui: Improve the branch picker when in the panel (#44408)

Danilo Leal created

This PR adapts the design for the panel version of the branch picker.


https://github.com/user-attachments/assets/d04b612b-72e8-4bc9-9a19-9d466b9fe696

Release Notes:

- N/A

Change summary

assets/icons/git_branch_plus.svg   |   8 ++
crates/git_ui/src/branch_picker.rs | 106 +++++++++++++++++++++++++++++++
crates/icons/src/icons.rs          |   1 
3 files changed, 112 insertions(+), 3 deletions(-)

Detailed changes

assets/icons/git_branch_plus.svg 🔗

@@ -0,0 +1,8 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 2V10" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12 6C12.5304 6 13.0391 5.78929 13.4142 5.41421C13.7893 5.03914 14 4.53043 14 4C14 3.46957 13.7893 2.96086 13.4142 2.58579C13.0391 2.21071 12.5304 2 12 2C11.4696 2 10.9609 2.21071 10.5858 2.58579C10.2107 2.96086 10 3.46957 10 4C10 4.53043 10.2107 5.03914 10.5858 5.41421C10.9609 5.78929 11.4696 6 12 6Z" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M4 14C4.53043 14 5.03914 13.7893 5.41421 13.4142C5.78929 13.0391 6 12.5304 6 12C6 11.4696 5.78929 10.9609 5.41421 10.5858C5.03914 10.2107 4.53043 10 4 10C3.46957 10 2.96086 10.2107 2.58579 10.5858C2.21071 10.9609 2 11.4696 2 12C2 12.5304 2.21071 13.0391 2.58579 13.4142C2.96086 13.7893 3.46957 14 4 14Z" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M10 4C8.4087 4 6.88258 4.63214 5.75736 5.75736C4.63214 6.88258 4 8.4087 4 10" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12 10V14" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M14 12H10" stroke="#C6CAD0" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

crates/git_ui/src/branch_picker.rs 🔗

@@ -551,6 +551,8 @@ impl PickerDelegate for BranchListDelegate {
             editor.set_placeholder_text(placeholder, window, cx);
         });
 
+        let focus_handle = self.focus_handle.clone();
+
         v_flex()
             .when(
                 self.editor_position() == PickerEditorPosition::End,
@@ -562,7 +564,37 @@ impl PickerDelegate for BranchListDelegate {
                     .flex_none()
                     .h_9()
                     .px_2p5()
-                    .child(editor.clone()),
+                    .child(editor.clone())
+                    .when(
+                        self.editor_position() == PickerEditorPosition::End,
+                        |this| {
+                            let tooltip_label = if self.display_remotes {
+                                "Turn Off Remote Filter"
+                            } else {
+                                "Filter Remote Branches"
+                            };
+
+                            this.gap_1().justify_between().child({
+                                IconButton::new("filter-remotes", IconName::Filter)
+                                    .disabled(self.loading)
+                                    .toggle_state(self.display_remotes)
+                                    .tooltip(move |_, cx| {
+                                        Tooltip::for_action_in(
+                                            tooltip_label,
+                                            &branch_picker::FilterRemotes,
+                                            &focus_handle,
+                                            cx,
+                                        )
+                                    })
+                                    .on_click(|_click, window, cx| {
+                                        window.dispatch_action(
+                                            branch_picker::FilterRemotes.boxed_clone(),
+                                            cx,
+                                        );
+                                    })
+                            })
+                        },
+                    ),
             )
             .when(
                 self.editor_position() == PickerEditorPosition::Start,
@@ -842,6 +874,42 @@ impl PickerDelegate for BranchListDelegate {
             }
         };
 
+        let focus_handle = self.focus_handle.clone();
+        let is_new_items = matches!(entry, Entry::NewUrl { .. } | Entry::NewBranch { .. });
+
+        let delete_branch_button = IconButton::new("delete", IconName::Trash)
+            .tooltip(move |_, cx| {
+                Tooltip::for_action_in(
+                    "Delete Branch",
+                    &branch_picker::DeleteBranch,
+                    &focus_handle,
+                    cx,
+                )
+            })
+            .on_click(cx.listener(|this, _, window, cx| {
+                let selected_idx = this.delegate.selected_index();
+                this.delegate.delete_at(selected_idx, window, cx);
+            }));
+
+        let create_from_default_button = self.default_branch.as_ref().map(|default_branch| {
+            let tooltip_label: SharedString = format!("Create New From: {default_branch}").into();
+            let focus_handle = self.focus_handle.clone();
+
+            IconButton::new("create_from_default", IconName::GitBranchPlus)
+                .tooltip(move |_, cx| {
+                    Tooltip::for_action_in(
+                        tooltip_label.clone(),
+                        &menu::SecondaryConfirm,
+                        &focus_handle,
+                        cx,
+                    )
+                })
+                .on_click(cx.listener(|this, _, window, cx| {
+                    this.delegate.confirm(true, window, cx);
+                }))
+                .into_any_element()
+        });
+
         Some(
             ListItem::new(SharedString::from(format!("vcs-menu-{ix}")))
                 .inset(true)
@@ -929,6 +997,34 @@ impl PickerDelegate for BranchListDelegate {
                                     |this, branch_name| this.tooltip(Tooltip::text(branch_name)),
                                 ),
                         ),
+                )
+                .when(
+                    self.editor_position() == PickerEditorPosition::End && !is_new_items,
+                    |this| {
+                        this.map(|this| {
+                            if self.selected_index() == ix {
+                                this.end_slot(delete_branch_button)
+                            } else {
+                                this.end_hover_slot(delete_branch_button)
+                            }
+                        })
+                    },
+                )
+                .when_some(
+                    if self.editor_position() == PickerEditorPosition::End && is_new_items {
+                        create_from_default_button
+                    } else {
+                        None
+                    },
+                    |this, create_from_default_button| {
+                        this.map(|this| {
+                            if self.selected_index() == ix {
+                                this.end_slot(create_from_default_button)
+                            } else {
+                                this.end_hover_slot(create_from_default_button)
+                            }
+                        })
+                    },
                 ),
         )
     }
@@ -950,6 +1046,10 @@ impl PickerDelegate for BranchListDelegate {
     }
 
     fn render_footer(&self, _: &mut Window, cx: &mut Context<Picker<Self>>) -> Option<AnyElement> {
+        if self.editor_position() == PickerEditorPosition::End {
+            return None;
+        }
+
         let focus_handle = self.focus_handle.clone();
         let loading_icon = Icon::new(IconName::LoadCircle)
             .size(IconSize::Small)
@@ -989,7 +1089,7 @@ impl PickerDelegate for BranchListDelegate {
                     });
 
                 let delete_and_select_btns = h_flex()
-                    .gap_0p5()
+                    .gap_1()
                     .child(
                         Button::new("delete-branch", "Delete")
                             .disabled(self.loading)
@@ -1093,7 +1193,7 @@ impl PickerDelegate for BranchListDelegate {
 
                 Some(
                     footer_container()
-                        .gap_0p5()
+                        .gap_1()
                         .justify_end()
                         .when_some(branch_from_default_button, |this, button| {
                             this.child(button)

crates/icons/src/icons.rs 🔗

@@ -136,6 +136,7 @@ pub enum IconName {
     GenericRestore,
     GitBranch,
     GitBranchAlt,
+    GitBranchPlus,
     Github,
     Hash,
     HistoryRerun,