git_ui: Add setting to control default click behavior for git panel (#59649)
Some checks are pending
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions

# Objective

The current behavior of the git panel is that when you click a file it
will open the multi-buffer view that shows all files with changes. If
you use CMD+Click or CTRL+Click, it will open the solo-file experience
where you only see the diff of the file you have selected. But, there is
no way to customize this behavior.

Related to:
https://github.com/zed-industries/zed/pull/56152#issuecomment-4641971669

## Solution

This MR adds a setting that allows you to customize the default click
behavior. The alternate behavior will always be accessible via CMD+Click
or CTRL+Click.

## Self-Review Checklist:

- [X] I've reviewed my own diff for quality, security, and reliability
- [X] Unsafe blocks (if any) have justifying comments
- [X] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [X] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable

---

Release Notes:

- Added a setting to control default click behavior for git panel files

---------

Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
This commit is contained in:
Nathan Fiscaletti 2026-06-21 21:00:15 -05:00 committed by GitHub
parent 356e396517
commit 514b14ed49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 98 additions and 9 deletions

View file

@ -1014,6 +1014,11 @@
//
// Default: 0
"commit_title_max_length": 0,
// Default action when clicking a changed file in the Git panel.
//
// Choices: project_diff, file_diff, view_file
// Default: project_diff
"entry_primary_click_action": "project_diff",
},
"message_editor": {
// Whether to automatically replace emoji shortcodes with emoji characters.

View file

@ -63,7 +63,8 @@ use prompt_store::RULES_FILE_NAMES;
use proto::RpcError;
use serde::{Deserialize, Serialize};
use settings::{
GitPanelGroupBy, GitPanelSortBy, Settings, SettingsStore, StatusStyle, update_settings_file,
GitPanelClickBehavior, GitPanelGroupBy, GitPanelSortBy, Settings, SettingsStore, StatusStyle,
update_settings_file,
};
use smallvec::SmallVec;
use std::future::Future;
@ -1489,6 +1490,36 @@ impl GitPanel {
});
}
fn open_selected_entry_on_click(
&mut self,
secondary: bool,
window: &mut Window,
cx: &mut Context<Self>,
) {
let entry_primary_click_action =
GitPanelSettings::get_global(cx).entry_primary_click_action;
let action = match (entry_primary_click_action, secondary) {
(GitPanelClickBehavior::ProjectDiff, false) => GitPanelClickBehavior::ProjectDiff,
(GitPanelClickBehavior::ProjectDiff, true) => GitPanelClickBehavior::FileDiff,
(GitPanelClickBehavior::FileDiff, false) => GitPanelClickBehavior::FileDiff,
(GitPanelClickBehavior::FileDiff, true) => GitPanelClickBehavior::ProjectDiff,
(GitPanelClickBehavior::ViewFile, false) => GitPanelClickBehavior::ViewFile,
(GitPanelClickBehavior::ViewFile, true) => GitPanelClickBehavior::ProjectDiff,
};
match action {
GitPanelClickBehavior::ProjectDiff => {
self.open_diff(&Default::default(), window, cx);
self.focus_handle.focus(window, cx);
}
GitPanelClickBehavior::FileDiff => {
self.open_solo_diff(&Default::default(), window, cx);
}
GitPanelClickBehavior::ViewFile => {
self.view_file(&Default::default(), window, cx);
}
}
}
fn revert_selected(
&mut self,
action: &git::RestoreFile,
@ -6493,12 +6524,7 @@ impl GitPanel {
cx.listener(move |this, event: &ClickEvent, window, cx| {
this.selected_entry = Some(ix);
cx.notify();
if event.modifiers().secondary() {
this.open_solo_diff(&Default::default(), window, cx)
} else {
this.open_diff(&Default::default(), window, cx);
this.focus_handle.focus(window, cx);
}
this.open_selected_entry_on_click(event.modifiers().secondary(), window, cx);
})
})
.on_mouse_down(

View file

@ -2,7 +2,9 @@ use editor::{EditorSettings, ui_scrollbar_settings_from_raw};
use gpui::Pixels;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{GitPanelGroupBy, GitPanelSortBy, RegisterSetting, Settings, StatusStyle};
use settings::{
GitPanelClickBehavior, GitPanelGroupBy, GitPanelSortBy, RegisterSetting, Settings, StatusStyle,
};
use ui::{
px,
scrollbars::{ScrollbarVisibility, ShowScrollbar},
@ -32,6 +34,7 @@ pub struct GitPanelSettings {
pub show_count_badge: bool,
pub starts_open: bool,
pub commit_title_max_length: usize,
pub entry_primary_click_action: GitPanelClickBehavior,
}
#[derive(Default)]
@ -80,6 +83,7 @@ impl Settings for GitPanelSettings {
show_count_badge: git_panel.show_count_badge.unwrap(),
starts_open: git_panel.starts_open.unwrap(),
commit_title_max_length: git_panel.commit_title_max_length.unwrap(),
entry_primary_click_action: git_panel.entry_primary_click_action.unwrap(),
}
}
}

View file

@ -718,6 +718,36 @@ pub struct GitPanelSettingsContent {
///
/// Default: 0
pub commit_title_max_length: Option<usize>,
/// Default action when clicking a changed file in the Git panel.
///
/// Default: project_diff
pub entry_primary_click_action: Option<GitPanelClickBehavior>,
}
#[derive(
Default,
Copy,
Clone,
Debug,
Serialize,
Deserialize,
JsonSchema,
MergeFrom,
PartialEq,
Eq,
strum::VariantArray,
strum::VariantNames,
)]
#[serde(rename_all = "snake_case")]
pub enum GitPanelClickBehavior {
/// Open the project diff, showing all changed files.
#[default]
ProjectDiff,
/// Open a single-file diff view.
FileDiff,
/// Open the file in the editor without a diff view.
ViewFile,
}
#[derive(

View file

@ -5776,7 +5776,7 @@ fn panels_page() -> SettingsPage {
]
}
fn git_panel_section() -> [SettingsPageItem; 16] {
fn git_panel_section() -> [SettingsPageItem; 17] {
[
SettingsPageItem::SectionHeader("Git Panel"),
SettingsPageItem::SettingItem(SettingItem {
@ -5992,6 +5992,29 @@ fn panels_page() -> SettingsPage {
metadata: None,
files: USER,
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Primary Click Behavior",
description: "Default action when clicking a changed file in the Git panel.",
field: Box::new(SettingField {
organization_override: None,
json_path: Some("git_panel.entry_primary_click_action"),
pick: |settings_content| {
settings_content
.git_panel
.as_ref()?
.entry_primary_click_action
.as_ref()
},
write: |settings_content, value, _| {
settings_content
.git_panel
.get_or_insert_default()
.entry_primary_click_action = value;
},
}),
metadata: None,
files: USER,
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Show Count Badge",
description: "Whether to show a badge on the git panel icon with the count of uncommitted changes.",

View file

@ -600,6 +600,7 @@ fn init_renderers(cx: &mut App) {
.add_basic_renderer::<settings::ThinkingBlockDisplay>(render_dropdown)
.add_basic_renderer::<settings::ImageFileSizeUnit>(render_dropdown)
.add_basic_renderer::<settings::StatusStyle>(render_dropdown)
.add_basic_renderer::<settings::GitPanelClickBehavior>(render_dropdown)
.add_basic_renderer::<settings::GitPanelSortBy>(render_dropdown)
.add_basic_renderer::<settings::GitPanelGroupBy>(render_dropdown)
.add_basic_renderer::<settings::EncodingDisplayOptions>(render_dropdown)