editor: Add configurable git gutter width setting (#61304)

## Summary

Adds a `gutter.git_gutter_width` setting that lets users pin the width,
in pixels, of the git diff hunk indicators in the editor gutter.

Previously the width was always derived from the buffer font size
(`floor(0.275 * line_height)`), which can render too thin or too thick
depending on font family and display pixel density. This adds an
optional override:

```json
{
  "gutter": {
    "git_gutter_width": 6
  }
}
```

When the setting is unset (`null`, the default), the width continues to
scale with the buffer font size, so existing behavior is unchanged.

## Motivation

Requested in [discussion
#27799](https://github.com/zed-industries/zed/discussions/27799). Beyond
the width itself, participants noted the git hunk hit target is
extremely narrow and hard to click. Because the hunk hitbox reuses the
painted strip bounds, setting a wider `git_gutter_width` also widens the
clickable area, addressing that complaint with the same setting.

## Changes

- `settings_content`: new `git_gutter_width: Option<f32>` on
`GutterContent`.
- `editor`: mirror field on the resolved `Gutter`; `gutter_strip_width`
now consults the setting, and the value flows through `diff_hunk_bounds`
(including the deleted-hunk marker) and the gutter layout anchors for
line numbers, folds, and expand toggles.
- `settings` (VS Code import): pass through the new field.
- Docs + `default.json`: document the new setting.

## Notes

- `Eq` was dropped from `GutterContent`/`Gutter` because `f32` is not
`Eq`; this matches the existing `EditorSettingsContent` convention for
float-bearing settings.

Release Notes:

- Added a `gutter.git_gutter_width` setting to configure the width of
git diff indicators in the editor gutter

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Evan VinciguerraandClaude Opus 4.8 authored and GitHub committed 2026-08-03 01:46:00 +00:00
1 parent 077311366d
commit 3b56897a51
7 files changed
+57 -11

No files matched your search

+3
View File
@@ -695,6 +695,9 @@
"folds": true,
// Minimum number of characters to reserve space for in the gutter.
"min_line_number_digits": 4,
// The width, in pixels, of the git diff hunk indicators in the gutter.
// When set to null, the width scales with the buffer font size.
"git_gutter_width": null,
},
"indent_guides": {
// Whether to show indent guides in the editor.
+3 -1
View File
@@ -141,7 +141,7 @@ impl Minimap {
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Gutter {
pub min_line_number_digits: usize,
pub line_numbers: bool,
@@ -149,6 +149,7 @@ pub struct Gutter {
pub breakpoints: bool,
pub bookmarks: bool,
pub folds: bool,
pub git_gutter_width: Option<f32>,
}
/// Forcefully enable or disable the scrollbar for each axis
@@ -267,6 +268,7 @@ impl Settings for EditorSettings {
bookmarks: gutter.bookmarks.unwrap(),
breakpoints: gutter.breakpoints.unwrap(),
folds: gutter.folds.unwrap(),
git_gutter_width: gutter.git_gutter_width,
},
scroll_beyond_last_line: editor.scroll_beyond_last_line.unwrap(),
vertical_scroll_margin: editor.vertical_scroll_margin.unwrap() as f64,
+16 -7
View File
@@ -1676,6 +1676,7 @@ impl EditorElement {
gutter_hitbox.bounds,
hunk,
snapshot,
cx,
);
*hitbox = Some(window.insert_hitbox(hunk_bounds, HitboxBehavior::BlockMouse));
}
@@ -2669,7 +2670,7 @@ impl EditorElement {
.ilog10()
+ 1;
let git_gutter_width = Self::gutter_strip_width(line_height)
let git_gutter_width = Self::gutter_strip_width(line_height, cx)
+ gutter_dimensions
.git_blame_entries_width
.unwrap_or_default();
@@ -5228,6 +5229,7 @@ impl EditorElement {
layout.gutter_hitbox.bounds,
hunk,
&layout.position_map.snapshot,
cx,
);
Some((
hunk_bounds,
@@ -5313,8 +5315,11 @@ impl EditorElement {
});
}
fn gutter_strip_width(line_height: Pixels) -> Pixels {
(0.275 * line_height).floor()
fn gutter_strip_width(line_height: Pixels, cx: &App) -> Pixels {
match EditorSettings::get_global(cx).gutter.git_gutter_width {
Some(width) => px(width),
None => (0.275 * line_height).floor(),
}
}
fn diff_hunk_bounds(
@@ -5323,9 +5328,10 @@ impl EditorElement {
gutter_bounds: Bounds<Pixels>,
hunk: &DisplayDiffHunk,
snapshot: &EditorSnapshot,
cx: &App,
) -> Bounds<Pixels> {
let scroll_top = scroll_position.y * ScrollPixelOffset::from(line_height);
let gutter_strip_width = Self::gutter_strip_width(line_height);
let gutter_strip_width = Self::gutter_strip_width(line_height, cx);
match hunk {
DisplayDiffHunk::Folded { display_row, .. } => {
@@ -5351,7 +5357,10 @@ impl EditorElement {
.into();
let end_y = start_y + line_height;
let width = (0.35 * line_height).floor();
let width = match EditorSettings::get_global(cx).gutter.git_gutter_width {
Some(width) => px(width),
None => (0.35 * line_height).floor(),
};
let highlight_origin = gutter_bounds.origin + point(px(0.), start_y);
let highlight_size = size(width, end_y - start_y);
Bounds::new(highlight_origin, highlight_size)
@@ -6720,7 +6729,7 @@ impl Gutter<'_> {
AvailableSpace::Definite(self.line_height),
);
let indicator_size = button.layout_as_root(available_space, window, cx);
let git_gutter_width = EditorElement::gutter_strip_width(self.line_height)
let git_gutter_width = EditorElement::gutter_strip_width(self.line_height, cx)
+ self.dimensions.git_blame_entries_width.unwrap_or_default();
let x = git_gutter_width + px(2.);
@@ -9148,7 +9157,7 @@ impl Element for EditorElement {
);
}
let git_gutter_width = Self::gutter_strip_width(line_height)
let git_gutter_width = Self::gutter_strip_width(line_height, cx)
+ gutter_dimensions
.git_blame_entries_width
.unwrap_or_default();
+1
View File
@@ -350,6 +350,7 @@ impl VsCodeSettings {
"never" => Some(false),
_ => None,
}),
git_gutter_width: None,
})
}
+6 -1
View File
@@ -483,7 +483,7 @@ pub struct ScrollbarAxesContent {
/// Gutter related settings
#[with_fallible_options]
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
pub struct GutterContent {
/// Whether to show line numbers in the gutter.
///
@@ -509,6 +509,11 @@ pub struct GutterContent {
///
/// Default: true
pub folds: Option<bool>,
/// The width, in pixels, of the git diff hunk indicators in the gutter.
/// When unset, the width scales with the buffer font size.
///
/// Default: null
pub git_gutter_width: Option<f32>,
}
/// Whether to display code lenses from language servers above code elements.
+25 -1
View File
@@ -2182,7 +2182,7 @@ fn editor_page() -> SettingsPage {
]
}
fn gutter_section() -> [SettingsPageItem; 9] {
fn gutter_section() -> [SettingsPageItem; 10] {
[
SettingsPageItem::SectionHeader("Gutter"),
SettingsPageItem::SettingItem(SettingItem {
@@ -2339,6 +2339,30 @@ fn editor_page() -> SettingsPage {
metadata: None,
files: USER,
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Git Gutter Width",
description: "Width, in pixels, of the git diff indicators in the gutter. When unset, the width scales with the buffer font size.",
field: Box::new(SettingField {
organization_override: None,
json_path: Some("gutter.git_gutter_width"),
pick: |settings_content| {
settings_content
.editor
.gutter
.as_ref()
.and_then(|gutter| gutter.git_gutter_width.as_ref())
},
write: |settings_content, value, _| {
settings_content
.editor
.gutter
.get_or_insert_default()
.git_gutter_width = value;
},
}),
metadata: None,
files: USER,
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Inline Code Actions",
description: "Show code action button at start of buffer line.",
+3 -1
View File
@@ -838,7 +838,8 @@ List of `string` values
"runnables": true,
"breakpoints": true,
"folds": true,
"min_line_number_digits": 4
"min_line_number_digits": 4,
"git_gutter_width": null
}
}
```
@@ -850,6 +851,7 @@ List of `string` values
- `breakpoints`: Whether to show breakpoints in the gutter
- `folds`: Whether to show fold buttons in the gutter
- `min_line_number_digits`: Minimum number of characters to reserve space for in the gutter
- `git_gutter_width`: The width, in pixels, of the git diff hunk indicators in the gutter. When `null`, the width scales with the buffer font size
## Hide Mouse