Fixed contrast in project panel and scrollbar

Mikayla Maki and nate created

co-authored-by: nate <nate@zed.dev>

Change summary

crates/diagnostics/src/diagnostics.rs     |  5 -
crates/editor/src/editor.rs               |  1 
crates/project_panel/src/project_panel.rs | 33 ++++++++-----
crates/theme/src/theme.rs                 | 23 +++++++++
crates/theme/src/ui.rs                    | 57 +-----------------------
styles/src/styleTree/editor.ts            | 41 ++++++++++++++---
styles/src/styleTree/projectPanel.ts      | 18 +++++++
7 files changed, 97 insertions(+), 81 deletions(-)

Detailed changes

crates/diagnostics/src/diagnostics.rs 🔗

@@ -105,9 +105,8 @@ impl View for ProjectDiagnosticsEditor {
     }
 
     fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
-        dbg!("Focus in");
-        if dbg!(cx.is_self_focused()) && dbg!(!self.path_states.is_empty()) {
-            dbg!(cx.focus(&self.editor));
+        if cx.is_self_focused() && !self.path_states.is_empty() {
+            cx.focus(&self.editor);
         }
     }
 

crates/editor/src/editor.rs 🔗

@@ -7253,7 +7253,6 @@ impl View for Editor {
     }
 
     fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
-        dbg!("Editor Focus in");
         if cx.is_self_focused() {
             let focused_event = EditorFocused(cx.handle());
             cx.emit(Event::Focused);

crates/project_panel/src/project_panel.rs 🔗

@@ -6,8 +6,8 @@ use gpui::{
     actions,
     anyhow::{anyhow, Result},
     elements::{
-        AnchorCorner, ChildView, ComponentHost, ContainerStyle, Empty, Flex, MouseEventHandler,
-        ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState,
+        AnchorCorner, ChildView, ContainerStyle, Empty, Flex, MouseEventHandler,
+        ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, Label,
     },
     geometry::vector::Vector2F,
     keymap_matcher::KeymapContext,
@@ -28,7 +28,7 @@ use std::{
     path::Path,
     sync::Arc,
 };
-use theme::{ui::FileName, ProjectPanelEntry};
+use theme::ProjectPanelEntry;
 use unicase::UniCase;
 use workspace::Workspace;
 
@@ -1079,6 +1079,17 @@ impl ProjectPanel {
         let kind = details.kind;
         let show_editor = details.is_editing && !details.is_processing;
 
+        let mut filename_text_style = style.text.clone();
+        filename_text_style.color = details
+            .git_status
+            .as_ref()
+            .map(|status| match status {
+                GitFileStatus::Added => style.status.git.inserted,
+                GitFileStatus::Modified => style.status.git.modified,
+                GitFileStatus::Conflict => style.status.git.conflict,
+            })
+            .unwrap_or(style.text.color);
+
         Flex::row()
             .with_child(
                 if kind == EntryKind::Dir {
@@ -1106,16 +1117,12 @@ impl ProjectPanel {
                     .flex(1.0, true)
                     .into_any()
             } else {
-                ComponentHost::new(FileName::new(
-                    details.filename.clone(),
-                    details.git_status,
-                    FileName::style(style.text.clone(), &theme::current(cx)),
-                ))
-                .contained()
-                .with_margin_left(style.icon_spacing)
-                .aligned()
-                .left()
-                .into_any()
+                Label::new(details.filename.clone(), filename_text_style)
+                    .contained()
+                    .with_margin_left(style.icon_spacing)
+                    .aligned()
+                    .left()
+                    .into_any()
             })
             .constrained()
             .with_height(style.height)

crates/theme/src/theme.rs 🔗

@@ -446,7 +446,20 @@ pub struct ProjectPanelEntry {
     pub icon_color: Color,
     pub icon_size: f32,
     pub icon_spacing: f32,
-}
+    pub status: EntryStatus,
+ }
+
+ #[derive(Clone, Debug, Deserialize, Default)]
+ pub struct EntryStatus {
+     pub git: GitProjectStatus,
+ }
+
+ #[derive(Clone, Debug, Deserialize, Default)]
+ pub struct GitProjectStatus {
+     pub modified: Color,
+     pub inserted: Color,
+     pub conflict: Color,
+ }
 
 #[derive(Clone, Debug, Deserialize, Default)]
 pub struct ContextMenu {
@@ -670,6 +683,14 @@ pub struct Scrollbar {
     pub thumb: ContainerStyle,
     pub width: f32,
     pub min_height_factor: f32,
+    pub git: GitDiffColors,
+}
+
+#[derive(Clone, Deserialize, Default)]
+pub struct GitDiffColors {
+    pub inserted: Color,
+    pub modified: Color,
+    pub deleted: Color,
 }
 
 #[derive(Clone, Deserialize, Default)]

crates/theme/src/ui.rs 🔗

@@ -1,10 +1,9 @@
 use std::borrow::Cow;
 
-use fs::repository::GitFileStatus;
 use gpui::{
     color::Color,
     elements::{
-        ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label, LabelStyle,
+        ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label,
         MouseEventHandler, ParentElement, Stack, Svg,
     },
     fonts::TextStyle,
@@ -12,11 +11,11 @@ use gpui::{
     platform,
     platform::MouseButton,
     scene::MouseClick,
-    Action, AnyElement, Element, EventContext, MouseState, View, ViewContext,
+    Action, Element, EventContext, MouseState, View, ViewContext,
 };
 use serde::Deserialize;
 
-use crate::{ContainedText, Interactive, Theme};
+use crate::{ContainedText, Interactive};
 
 #[derive(Clone, Deserialize, Default)]
 pub struct CheckboxStyle {
@@ -253,53 +252,3 @@ where
         .constrained()
         .with_height(style.dimensions().y())
 }
-
-pub struct FileName {
-    filename: String,
-    git_status: Option<GitFileStatus>,
-    style: FileNameStyle,
-}
-
-pub struct FileNameStyle {
-    template_style: LabelStyle,
-    git_inserted: Color,
-    git_modified: Color,
-    git_deleted: Color,
-}
-
-impl FileName {
-    pub fn new(filename: String, git_status: Option<GitFileStatus>, style: FileNameStyle) -> Self {
-        FileName {
-            filename,
-            git_status,
-            style,
-        }
-    }
-
-    pub fn style<I: Into<LabelStyle>>(style: I, theme: &Theme) -> FileNameStyle {
-        FileNameStyle {
-            template_style: style.into(),
-            git_inserted: theme.editor.diff.inserted,
-            git_modified: theme.editor.diff.modified,
-            git_deleted: theme.editor.diff.deleted,
-        }
-    }
-}
-
-impl<V: View> gpui::elements::Component<V> for FileName {
-    fn render(&self, _: &mut V, _: &mut ViewContext<V>) -> AnyElement<V> {
-        // Prepare colors for git statuses
-        let mut filename_text_style = self.style.template_style.text.clone();
-        filename_text_style.color = self
-            .git_status
-            .as_ref()
-            .map(|status| match status {
-                GitFileStatus::Added => self.style.git_inserted,
-                GitFileStatus::Modified => self.style.git_modified,
-                GitFileStatus::Conflict => self.style.git_deleted,
-            })
-            .unwrap_or(self.style.template_style.text.color);
-
-        Label::new(self.filename.clone(), filename_text_style).into_any()
-    }
-}

styles/src/styleTree/editor.ts 🔗

@@ -6,6 +6,8 @@ import hoverPopover from "./hoverPopover"
 import { SyntaxHighlightStyle, buildSyntax } from "../themes/common/syntax"
 
 export default function editor(colorScheme: ColorScheme) {
+    const { isLight } = colorScheme
+
     let layer = colorScheme.highest
 
     const autocompleteItem = {
@@ -97,12 +99,18 @@ export default function editor(colorScheme: ColorScheme) {
             foldBackground: foreground(layer, "variant"),
         },
         diff: {
-            deleted: foreground(layer, "negative"),
-            modified: foreground(layer, "warning"),
-            inserted: foreground(layer, "positive"),
+            deleted: isLight
+                ? colorScheme.ramps.red(0.5).hex()
+                : colorScheme.ramps.red(0.4).hex(),
+            modified: isLight
+                ? colorScheme.ramps.yellow(0.3).hex()
+                : colorScheme.ramps.yellow(0.5).hex(),
+            inserted: isLight
+                ? colorScheme.ramps.green(0.4).hex()
+                : colorScheme.ramps.green(0.5).hex(),
             removedWidthEm: 0.275,
-            widthEm: 0.22,
-            cornerRadius: 0.2,
+            widthEm: 0.15,
+            cornerRadius: 0.05,
         },
         /** Highlights matching occurences of what is under the cursor
          * as well as matched brackets
@@ -234,12 +242,27 @@ export default function editor(colorScheme: ColorScheme) {
                 border: border(layer, "variant", { left: true }),
             },
             thumb: {
-                background: withOpacity(background(layer, "inverted"), 0.4),
+                background: withOpacity(background(layer, "inverted"), 0.3),
                 border: {
-                    width: 1,
-                    color: borderColor(layer, "variant"),
-                },
+                        width: 1,
+                        color: borderColor(layer, "variant"),
+                        top: false,
+                        right: true,
+                        left: true,
+                        bottom: false,
+                }
             },
+            git: {
+                deleted: isLight
+                    ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
+                    : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
+                modified: isLight
+                    ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
+                    : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
+                inserted: isLight
+                    ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
+                    : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
+            }
         },
         compositionMark: {
             underline: {

styles/src/styleTree/projectPanel.ts 🔗

@@ -3,6 +3,8 @@ import { withOpacity } from "../utils/color"
 import { background, border, foreground, text } from "./components"
 
 export default function projectPanel(colorScheme: ColorScheme) {
+    const { isLight } = colorScheme
+
     let layer = colorScheme.middle
 
     let baseEntry = {
@@ -12,6 +14,20 @@ export default function projectPanel(colorScheme: ColorScheme) {
         iconSpacing: 8,
     }
 
+    let status = {
+        git: {
+            modified: isLight
+                ? colorScheme.ramps.yellow(0.6).hex()
+                : colorScheme.ramps.yellow(0.5).hex(),
+            inserted: isLight
+                ? colorScheme.ramps.green(0.45).hex()
+                : colorScheme.ramps.green(0.5).hex(),
+            conflict: isLight
+                ? colorScheme.ramps.red(0.6).hex()
+                : colorScheme.ramps.red(0.5).hex()
+        }
+    }
+
     let entry = {
         ...baseEntry,
         text: text(layer, "mono", "variant", { size: "sm" }),
@@ -28,6 +44,7 @@ export default function projectPanel(colorScheme: ColorScheme) {
             background: background(layer, "active"),
             text: text(layer, "mono", "active", { size: "sm" }),
         },
+        status
     }
 
     return {
@@ -62,6 +79,7 @@ export default function projectPanel(colorScheme: ColorScheme) {
             text: text(layer, "mono", "on", { size: "sm" }),
             background: withOpacity(background(layer, "on"), 0.9),
             border: border(layer),
+            status
         },
         ignoredEntry: {
             ...entry,