From 87014cec71335c6ae20fbe3fe6299f95542103c4 Mon Sep 17 00:00:00 2001
From: Bret Comnes <166301+bcomnes@users.noreply.github.com>
Date: Tue, 22 Jul 2025 02:50:26 -0700
Subject: [PATCH] theme: Add `panel.overlay_background` and
`panel.overlay_hover` (#34655)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In https://github.com/zed-industries/zed/pull/33994 sticky scroll was
added to project_panel.
I love this feature!
This introduces a new element layering not seen before. On themes that
use transparency, the overlapping elements can make it difficult to read
project panel entries. This PR introduces a new selector:
~~panel.sticky_entry.background~~ `panel.overlay_background` This
selector lets you set the background of entries when they become sticky.
Closes https://github.com/zed-industries/zed/issues/34654
Before:
After:
Release Notes:
- Add `panel.sticky_entry.background` theme selector for modifying
project panel entries when they become sticky when scrolling and overlap
with entries below them.
---------
Co-authored-by: Smit Barmase
---
crates/project_panel/src/project_panel.rs | 16 ++++++++---
crates/theme/src/default_colors.rs | 4 +++
crates/theme/src/fallback_themes.rs | 9 ++++--
crates/theme/src/schema.rs | 34 +++++++++++++++++------
crates/theme/src/styles/colors.rs | 10 +++++++
5 files changed, 58 insertions(+), 15 deletions(-)
diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs
index b6fdcd6fa5..44f4e8985a 100644
--- a/crates/project_panel/src/project_panel.rs
+++ b/crates/project_panel/src/project_panel.rs
@@ -384,12 +384,20 @@ struct ItemColors {
focused: Hsla,
}
-fn get_item_color(cx: &App) -> ItemColors {
+fn get_item_color(is_sticky: bool, cx: &App) -> ItemColors {
let colors = cx.theme().colors();
ItemColors {
- default: colors.panel_background,
- hover: colors.element_hover,
+ default: if is_sticky {
+ colors.panel_overlay_background
+ } else {
+ colors.panel_background
+ },
+ hover: if is_sticky {
+ colors.panel_overlay_hover
+ } else {
+ colors.element_hover
+ },
marked: colors.element_selected,
focused: colors.panel_focused_border,
drag_over: colors.drop_target_background,
@@ -3903,7 +3911,7 @@ impl ProjectPanel {
let filename_text_color = details.filename_text_color;
let diagnostic_severity = details.diagnostic_severity;
- let item_colors = get_item_color(cx);
+ let item_colors = get_item_color(is_sticky, cx);
let canonical_path = details
.canonical_path
diff --git a/crates/theme/src/default_colors.rs b/crates/theme/src/default_colors.rs
index 3424e0fe04..1c3f48b548 100644
--- a/crates/theme/src/default_colors.rs
+++ b/crates/theme/src/default_colors.rs
@@ -83,6 +83,8 @@ impl ThemeColors {
panel_indent_guide: neutral().light_alpha().step_5(),
panel_indent_guide_hover: neutral().light_alpha().step_6(),
panel_indent_guide_active: neutral().light_alpha().step_6(),
+ panel_overlay_background: neutral().light().step_2(),
+ panel_overlay_hover: neutral().light_alpha().step_4(),
pane_focused_border: blue().light().step_5(),
pane_group_border: neutral().light().step_6(),
scrollbar_thumb_background: neutral().light_alpha().step_3(),
@@ -206,6 +208,8 @@ impl ThemeColors {
panel_indent_guide: neutral().dark_alpha().step_4(),
panel_indent_guide_hover: neutral().dark_alpha().step_6(),
panel_indent_guide_active: neutral().dark_alpha().step_6(),
+ panel_overlay_background: neutral().dark().step_2(),
+ panel_overlay_hover: neutral().dark_alpha().step_4(),
pane_focused_border: blue().dark().step_5(),
pane_group_border: neutral().dark().step_6(),
scrollbar_thumb_background: neutral().dark_alpha().step_3(),
diff --git a/crates/theme/src/fallback_themes.rs b/crates/theme/src/fallback_themes.rs
index 5e9967d460..4d77dd5d81 100644
--- a/crates/theme/src/fallback_themes.rs
+++ b/crates/theme/src/fallback_themes.rs
@@ -59,6 +59,7 @@ pub(crate) fn zed_default_dark() -> Theme {
let bg = hsla(215. / 360., 12. / 100., 15. / 100., 1.);
let editor = hsla(220. / 360., 12. / 100., 18. / 100., 1.);
let elevated_surface = hsla(225. / 360., 12. / 100., 17. / 100., 1.);
+ let hover = hsla(225.0 / 360., 11.8 / 100., 26.7 / 100., 1.0);
let blue = hsla(207.8 / 360., 81. / 100., 66. / 100., 1.0);
let gray = hsla(218.8 / 360., 10. / 100., 40. / 100., 1.0);
@@ -108,14 +109,14 @@ pub(crate) fn zed_default_dark() -> Theme {
surface_background: bg,
background: bg,
element_background: hsla(223.0 / 360., 13. / 100., 21. / 100., 1.0),
- element_hover: hsla(225.0 / 360., 11.8 / 100., 26.7 / 100., 1.0),
+ element_hover: hover,
element_active: hsla(220.0 / 360., 11.8 / 100., 20.0 / 100., 1.0),
element_selected: hsla(224.0 / 360., 11.3 / 100., 26.1 / 100., 1.0),
element_disabled: SystemColors::default().transparent,
element_selection_background: player.local().selection.alpha(0.25),
drop_target_background: hsla(220.0 / 360., 8.3 / 100., 21.4 / 100., 1.0),
ghost_element_background: SystemColors::default().transparent,
- ghost_element_hover: hsla(225.0 / 360., 11.8 / 100., 26.7 / 100., 1.0),
+ ghost_element_hover: hover,
ghost_element_active: hsla(220.0 / 360., 11.8 / 100., 20.0 / 100., 1.0),
ghost_element_selected: hsla(224.0 / 360., 11.3 / 100., 26.1 / 100., 1.0),
ghost_element_disabled: SystemColors::default().transparent,
@@ -202,10 +203,12 @@ pub(crate) fn zed_default_dark() -> Theme {
panel_indent_guide: hsla(228. / 360., 8. / 100., 25. / 100., 1.),
panel_indent_guide_hover: hsla(225. / 360., 13. / 100., 12. / 100., 1.),
panel_indent_guide_active: hsla(225. / 360., 13. / 100., 12. / 100., 1.),
+ panel_overlay_background: bg,
+ panel_overlay_hover: hover,
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_hover_background: hover,
scrollbar_thumb_active_background: hsla(
225.0 / 360.,
11.8 / 100.,
diff --git a/crates/theme/src/schema.rs b/crates/theme/src/schema.rs
index bed25d0c05..bfa2adcedf 100644
--- a/crates/theme/src/schema.rs
+++ b/crates/theme/src/schema.rs
@@ -351,6 +351,12 @@ pub struct ThemeColorsContent {
#[serde(rename = "panel.indent_guide_active")]
pub panel_indent_guide_active: Option,
+ #[serde(rename = "panel.overlay_background")]
+ pub panel_overlay_background: Option,
+
+ #[serde(rename = "panel.overlay_hover")]
+ pub panel_overlay_hover: Option,
+
#[serde(rename = "pane.focused_border")]
pub pane_focused_border: Option,
@@ -674,6 +680,14 @@ impl ThemeColorsContent {
.scrollbar_thumb_border
.as_ref()
.and_then(|color| try_parse_color(color).ok());
+ let element_hover = self
+ .element_hover
+ .as_ref()
+ .and_then(|color| try_parse_color(color).ok());
+ let panel_background = self
+ .panel_background
+ .as_ref()
+ .and_then(|color| try_parse_color(color).ok());
ThemeColorsRefinement {
border,
border_variant: self
@@ -712,10 +726,7 @@ impl ThemeColorsContent {
.element_background
.as_ref()
.and_then(|color| try_parse_color(color).ok()),
- element_hover: self
- .element_hover
- .as_ref()
- .and_then(|color| try_parse_color(color).ok()),
+ element_hover,
element_active: self
.element_active
.as_ref()
@@ -832,10 +843,7 @@ impl ThemeColorsContent {
.search_match_background
.as_ref()
.and_then(|color| try_parse_color(color).ok()),
- panel_background: self
- .panel_background
- .as_ref()
- .and_then(|color| try_parse_color(color).ok()),
+ panel_background,
panel_focused_border: self
.panel_focused_border
.as_ref()
@@ -852,6 +860,16 @@ impl ThemeColorsContent {
.panel_indent_guide_active
.as_ref()
.and_then(|color| try_parse_color(color).ok()),
+ panel_overlay_background: self
+ .panel_overlay_background
+ .as_ref()
+ .and_then(|color| try_parse_color(color).ok())
+ .or(panel_background),
+ panel_overlay_hover: self
+ .panel_overlay_hover
+ .as_ref()
+ .and_then(|color| try_parse_color(color).ok())
+ .or(element_hover),
pane_focused_border: self
.pane_focused_border
.as_ref()
diff --git a/crates/theme/src/styles/colors.rs b/crates/theme/src/styles/colors.rs
index 7c5270e361..aab11803f4 100644
--- a/crates/theme/src/styles/colors.rs
+++ b/crates/theme/src/styles/colors.rs
@@ -131,6 +131,12 @@ pub struct ThemeColors {
pub panel_indent_guide: Hsla,
pub panel_indent_guide_hover: Hsla,
pub panel_indent_guide_active: Hsla,
+
+ /// The color of the overlay surface on top of panel.
+ pub panel_overlay_background: Hsla,
+ /// The color of the overlay surface on top of panel when hovered over.
+ pub panel_overlay_hover: Hsla,
+
pub pane_focused_border: Hsla,
pub pane_group_border: Hsla,
/// The color of the scrollbar thumb.
@@ -326,6 +332,8 @@ pub enum ThemeColorField {
PanelIndentGuide,
PanelIndentGuideHover,
PanelIndentGuideActive,
+ PanelOverlayBackground,
+ PanelOverlayHover,
PaneFocusedBorder,
PaneGroupBorder,
ScrollbarThumbBackground,
@@ -438,6 +446,8 @@ impl ThemeColors {
ThemeColorField::PanelIndentGuide => self.panel_indent_guide,
ThemeColorField::PanelIndentGuideHover => self.panel_indent_guide_hover,
ThemeColorField::PanelIndentGuideActive => self.panel_indent_guide_active,
+ ThemeColorField::PanelOverlayBackground => self.panel_overlay_background,
+ ThemeColorField::PanelOverlayHover => self.panel_overlay_hover,
ThemeColorField::PaneFocusedBorder => self.pane_focused_border,
ThemeColorField::PaneGroupBorder => self.pane_group_border,
ThemeColorField::ScrollbarThumbBackground => self.scrollbar_thumb_background,