From 12dba5edbe78c334e1d19e2ba906ce022c15ca31 Mon Sep 17 00:00:00 2001
From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Date: Mon, 8 Dec 2025 12:20:58 -0300
Subject: [PATCH] git_ui: Improve the branch picker when in the panel (#44408)
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
---
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(-)
create mode 100644 assets/icons/git_branch_plus.svg
diff --git a/assets/icons/git_branch_plus.svg b/assets/icons/git_branch_plus.svg
new file mode 100644
index 0000000000000000000000000000000000000000..cf60ce66b4086ba57ef4c2e56f3554d548e863fc
--- /dev/null
+++ b/assets/icons/git_branch_plus.svg
@@ -0,0 +1,8 @@
+
diff --git a/crates/git_ui/src/branch_picker.rs b/crates/git_ui/src/branch_picker.rs
index 06405651206befad38c938c9fec35a98dab1ef2c..e198fa092e0cc2d0e8b77ba954fd743512915c75 100644
--- a/crates/git_ui/src/branch_picker.rs
+++ b/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>) -> Option {
+ 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)
diff --git a/crates/icons/src/icons.rs b/crates/icons/src/icons.rs
index d79660356f04fd42425d9e549764a4c202d29d43..cc84129250cfdbe968aa3d86f1d00d0789d01480 100644
--- a/crates/icons/src/icons.rs
+++ b/crates/icons/src/icons.rs
@@ -136,6 +136,7 @@ pub enum IconName {
GenericRestore,
GitBranch,
GitBranchAlt,
+ GitBranchPlus,
Github,
Hash,
HistoryRerun,