themes: Add `pane_group.border` color (#9986)

Andrew Lygin and Marshall Bowers created

This PR adds the `pane_group.border` theme attribute that defines the
color of the borders between pane groups.

- Defaults to the `border` color, so nothing changes in the existing
themes.
- VSCode theme converter takes it from the `editorGroup.border`.

The borders marked by red are affected:

<img width="878" alt="pane_group_borders"
src="https://github.com/zed-industries/zed/assets/2101250/54b9fd39-b3e1-4898-a047-ee0b6ec953ed">

Release Notes:

- Added `pane_group.border` to the theme for modifying the border color
for panes within a pane group.

Related Issues:

- First discussed in
https://github.com/zed-industries/zed/pull/9754#issuecomment-2026497213

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>

Change summary

crates/theme/src/default_colors.rs            |  2 ++
crates/theme/src/one_themes.rs                |  1 +
crates/theme/src/schema.rs                    | 17 +++++++++++++----
crates/theme/src/styles/colors.rs             |  1 +
crates/theme_importer/src/vscode/converter.rs |  1 +
crates/workspace/src/pane_group.rs            |  2 +-
6 files changed, 19 insertions(+), 5 deletions(-)

Detailed changes

crates/theme/src/default_colors.rs 🔗

@@ -58,6 +58,7 @@ impl ThemeColors {
             panel_background: neutral().light().step_2(),
             panel_focused_border: blue().light().step_5(),
             pane_focused_border: blue().light().step_5(),
+            pane_group_border: neutral().light().step_6(),
             scrollbar_thumb_background: neutral().light_alpha().step_3(),
             scrollbar_thumb_hover_background: neutral().light_alpha().step_4(),
             scrollbar_thumb_border: gpui::transparent_black(),
@@ -152,6 +153,7 @@ impl ThemeColors {
             panel_background: neutral().dark().step_2(),
             panel_focused_border: blue().dark().step_5(),
             pane_focused_border: blue().dark().step_5(),
+            pane_group_border: neutral().dark().step_6(),
             scrollbar_thumb_background: neutral().dark_alpha().step_3(),
             scrollbar_thumb_hover_background: neutral().dark_alpha().step_4(),
             scrollbar_thumb_border: gpui::transparent_black(),

crates/theme/src/one_themes.rs 🔗

@@ -131,6 +131,7 @@ pub(crate) fn one_dark() -> Theme {
                 panel_background: bg,
                 panel_focused_border: blue,
                 pane_focused_border: blue,
+                pane_group_border: hsla(225. / 360., 13. / 100., 12. / 100., 1.),
                 scrollbar_thumb_background: gpui::transparent_black(),
                 scrollbar_thumb_hover_background: hsla(225.0 / 360., 11.8 / 100., 26.7 / 100., 1.0),
                 scrollbar_thumb_border: hsla(228. / 360., 8. / 100., 25. / 100., 1.),

crates/theme/src/schema.rs 🔗

@@ -317,6 +317,9 @@ pub struct ThemeColorsContent {
     #[serde(rename = "pane.focused_border")]
     pub pane_focused_border: Option<String>,
 
+    #[serde(rename = "pane_group.border")]
+    pub pane_group_border: Option<String>,
+
     /// The color of the scrollbar thumb.
     #[serde(
         rename = "scrollbar.thumb.background",
@@ -513,11 +516,12 @@ pub struct ThemeColorsContent {
 impl ThemeColorsContent {
     /// Returns a [`ThemeColorsRefinement`] based on the colors in the [`ThemeColorsContent`].
     pub fn theme_colors_refinement(&self) -> ThemeColorsRefinement {
+        let border = self
+            .border
+            .as_ref()
+            .and_then(|color| try_parse_color(color).ok());
         ThemeColorsRefinement {
-            border: self
-                .border
-                .as_ref()
-                .and_then(|color| try_parse_color(color).ok()),
+            border,
             border_variant: self
                 .border_variant
                 .as_ref()
@@ -674,6 +678,11 @@ impl ThemeColorsContent {
                 .pane_focused_border
                 .as_ref()
                 .and_then(|color| try_parse_color(color).ok()),
+            pane_group_border: self
+                .pane_group_border
+                .as_ref()
+                .and_then(|color| try_parse_color(color).ok())
+                .or(border),
             scrollbar_thumb_background: self
                 .scrollbar_thumb_background
                 .as_ref()

crates/theme/src/styles/colors.rs 🔗

@@ -119,6 +119,7 @@ pub struct ThemeColors {
     pub panel_background: Hsla,
     pub panel_focused_border: Hsla,
     pub pane_focused_border: Hsla,
+    pub pane_group_border: Hsla,
     /// The color of the scrollbar thumb.
     pub scrollbar_thumb_background: Hsla,
     /// The color of the scrollbar thumb when hovered over.

crates/theme_importer/src/vscode/converter.rs 🔗

@@ -167,6 +167,7 @@ impl VsCodeThemeConverter {
             scrollbar_thumb_border: vscode_scrollbar_slider_background.clone(),
             scrollbar_track_background: vscode_editor_background.clone(),
             scrollbar_track_border: vscode_colors.editor_overview_ruler.border.clone(),
+            pane_group_border: vscode_colors.editor_group.border.clone(),
             editor_foreground: vscode_editor_foreground
                 .clone()
                 .or(vscode_token_colors_foreground.clone()),

crates/workspace/src/pane_group.rs 🔗

@@ -914,7 +914,7 @@ mod element {
                     cx.set_cursor_style(cursor_style, &handle.hitbox);
                     cx.paint_quad(gpui::fill(
                         handle.divider_bounds,
-                        cx.theme().colors().border,
+                        cx.theme().colors().pane_group_border,
                     ));
 
                     cx.on_mouse_event({