Merge pull request #1414 from zed-industries/fix-theme-issues

Keith Simmons created

Fix tab bar themes

Change summary

crates/project_panel/src/project_panel.rs |  4 
crates/theme/src/theme.rs                 | 22 +++++-
crates/workspace/src/pane.rs              | 35 ++++-----
styles/src/styleTree/tabBar.ts            | 85 +++++++++++++++++++++++++
styles/src/styleTree/workspace.ts         | 64 ------------------
styles/src/themes/common/base16.ts        |  4 
6 files changed, 123 insertions(+), 91 deletions(-)

Detailed changes

crates/project_panel/src/project_panel.rs 🔗

@@ -1028,11 +1028,11 @@ impl ProjectPanel {
                 .with_child(
                     ConstrainedBox::new(if kind == EntryKind::Dir {
                         if details.is_expanded {
-                            Svg::new("icons/chevron_right_8.svg")
+                            Svg::new("icons/chevron_down_8.svg")
                                 .with_color(style.icon_color)
                                 .boxed()
                         } else {
-                            Svg::new("icons/chevron_down_8.svg")
+                            Svg::new("icons/chevron_right_8.svg")
                                 .with_color(style.icon_color)
                                 .boxed()
                         }

crates/theme/src/theme.rs 🔗

@@ -38,11 +38,7 @@ pub struct Theme {
 pub struct Workspace {
     pub background: Color,
     pub titlebar: Titlebar,
-    pub active_pane_active_tab: Tab,
-    pub active_pane_inactive_tab: Tab,
-    pub inactive_pane_active_tab: Tab,
-    pub inactive_pane_inactive_tab: Tab,
-    pub pane_button: Interactive<IconButton>,
+    pub tab_bar: TabBar,
     pub pane_divider: Border,
     pub leader_border_opacity: f32,
     pub leader_border_width: f32,
@@ -72,6 +68,22 @@ pub struct Titlebar {
     pub outdated_warning: ContainedText,
 }
 
+#[derive(Clone, Deserialize, Default)]
+pub struct TabBar {
+    #[serde(flatten)]
+    pub container: ContainerStyle,
+    pub pane_button: Interactive<IconButton>,
+    pub active_pane: TabStyles,
+    pub inactive_pane: TabStyles,
+    pub height: f32,
+}
+
+#[derive(Clone, Deserialize, Default)]
+pub struct TabStyles {
+    pub active_tab: Tab,
+    pub inactive_tab: Tab,
+}
+
 #[derive(Clone, Deserialize, Default)]
 pub struct AvatarRibbon {
     #[serde(flatten)]

crates/workspace/src/pane.rs 🔗

@@ -873,6 +873,13 @@ impl Pane {
             };
 
             let is_pane_active = self.is_active;
+
+            let tab_styles = match is_pane_active {
+                true => theme.workspace.tab_bar.active_pane.clone(),
+                false => theme.workspace.tab_bar.inactive_pane.clone(),
+            };
+            let filler_style = tab_styles.inactive_tab.clone();
+
             let mut row = Flex::row().scrollable::<Tabs, _>(1, autoscroll, cx);
             for (ix, (item, detail)) in self.items.iter().zip(self.tab_details(cx)).enumerate() {
                 let item_id = item.id();
@@ -890,12 +897,11 @@ impl Pane {
                 };
 
                 row.add_child({
-                    let mut tab_style = match (is_pane_active, is_tab_active) {
-                        (true, true) => theme.workspace.active_pane_active_tab.clone(),
-                        (true, false) => theme.workspace.active_pane_inactive_tab.clone(),
-                        (false, true) => theme.workspace.inactive_pane_active_tab.clone(),
-                        (false, false) => theme.workspace.inactive_pane_inactive_tab.clone(),
+                    let mut tab_style = match is_tab_active {
+                        true => tab_styles.active_tab.clone(),
+                        false => tab_styles.inactive_tab.clone(),
                     };
+
                     let title = item.tab_content(detail, &tab_style, cx);
 
                     if ix == 0 {
@@ -1003,17 +1009,11 @@ impl Pane {
                 })
             }
 
-            let filler_style = if is_pane_active {
-                &theme.workspace.active_pane_inactive_tab
-            } else {
-                &theme.workspace.inactive_pane_inactive_tab
-            };
-
             row.add_child(
                 Empty::new()
                     .contained()
                     .with_style(filler_style.container)
-                    .with_border(theme.workspace.active_pane_active_tab.container.border)
+                    .with_border(filler_style.container.border)
                     .flex(0., true)
                     .named("filler"),
             );
@@ -1088,7 +1088,8 @@ impl View for Pane {
                                         0,
                                         cx,
                                         |mouse_state, cx| {
-                                            let theme = &cx.global::<Settings>().theme.workspace;
+                                            let theme =
+                                                &cx.global::<Settings>().theme.workspace.tab_bar;
                                             let style =
                                                 theme.pane_button.style_for(mouse_state, false);
                                             Svg::new("icons/split_12.svg")
@@ -1118,13 +1119,7 @@ impl View for Pane {
 
                             tab_row
                                 .constrained()
-                                .with_height(
-                                    cx.global::<Settings>()
-                                        .theme
-                                        .workspace
-                                        .active_pane_active_tab
-                                        .height,
-                                )
+                                .with_height(cx.global::<Settings>().theme.workspace.tab_bar.height)
                                 .boxed()
                         })
                         .with_child(ChildView::new(&self.toolbar).boxed())

styles/src/styleTree/tabBar.ts 🔗

@@ -0,0 +1,85 @@
+import Theme from "../themes/common/theme";
+import { iconColor, text, border, backgroundColor } from "./components";
+
+export default function tabBar(theme: Theme) {
+  const height = 32;
+
+  const tab = {
+    height,
+    background: backgroundColor(theme, 300),
+    border: border(theme, "primary", {
+      left: true,
+      bottom: true,
+      overlay: true,
+    }),
+    iconClose: iconColor(theme, "muted"),
+    iconCloseActive: iconColor(theme, "active"),
+    iconConflict: iconColor(theme, "warning"),
+    iconDirty: iconColor(theme, "info"),
+    iconWidth: 8,
+    spacing: 8,
+    text: text(theme, "sans", "secondary", { size: "sm" }),
+    padding: {
+      left: 8,
+      right: 8,
+    },
+    description: {
+      margin: { left: 6, top: 1 },
+      ...text(theme, "sans", "muted", { size: "2xs" })
+    }
+  };
+
+  const activePaneActiveTab = {
+    ...tab,
+    background: backgroundColor(theme, 500),
+    text: text(theme, "sans", "active", { size: "sm" }),
+    border: {
+      ...tab.border,
+    },
+  };
+
+  const inactivePaneInactiveTab = {
+    ...tab,
+    background: backgroundColor(theme, 300),
+    text: text(theme, "sans", "muted", { size: "sm" }),
+  };
+
+  const inactivePaneActiveTab = {
+    ...tab,
+    background: backgroundColor(theme, 500),
+    text: text(theme, "sans", "secondary", { size: "sm" }),
+    border: {
+      ...tab.border,
+    },
+  }
+
+  return {
+    height,
+    background: backgroundColor(theme, 300),
+    border: border(theme, "primary", {
+      left: true,
+      bottom: true,
+      overlay: true,
+    }),
+    activePane: {
+      activeTab: activePaneActiveTab,
+      inactiveTab: tab,
+    },
+    inactivePane: {
+      activeTab: inactivePaneActiveTab,
+      inactiveTab: inactivePaneInactiveTab,
+    },
+    paneButton: {
+      color: iconColor(theme, "secondary"),
+      border: {
+        ...activePaneActiveTab.border,
+      },
+      iconWidth: 12,
+      buttonWidth: activePaneActiveTab.height,
+      hover: {
+        color: iconColor(theme, "active"),
+        background: backgroundColor(theme, 300),
+      },
+    },
+  }
+}

styles/src/styleTree/workspace.ts 🔗

@@ -8,58 +8,13 @@ import {
   text,
 } from "./components";
 import statusBar from "./statusBar";
+import tabBar from "./tabBar";
 
 export function workspaceBackground(theme: Theme) {
   return backgroundColor(theme, 300);
 }
 
 export default function workspace(theme: Theme) {
-  const activePaneInactiveTab = {
-    height: 32,
-    background: workspaceBackground(theme),
-    iconClose: iconColor(theme, "muted"),
-    iconCloseActive: iconColor(theme, "active"),
-    iconConflict: iconColor(theme, "warning"),
-    iconDirty: iconColor(theme, "info"),
-    iconWidth: 8,
-    spacing: 8,
-    text: text(theme, "sans", "secondary", { size: "sm" }),
-    border: border(theme, "primary", {
-      left: true,
-      bottom: true,
-      overlay: true,
-    }),
-    padding: {
-      left: 8,
-      right: 8,
-    },
-    description: {
-      margin: { left: 6, top: 1 },
-      ...text(theme, "sans", "muted", { size: "2xs" })
-    }
-  };
-
-  const activePaneActiveTab = {
-    ...activePaneInactiveTab,
-    background: backgroundColor(theme, 500),
-    text: text(theme, "sans", "active", { size: "sm" }),
-    border: {
-      ...activePaneInactiveTab.border,
-      bottom: false,
-    },
-  };
-
-  const inactivePaneInactiveTab = {
-    ...activePaneInactiveTab,
-    background: backgroundColor(theme, 100),
-    text: text(theme, "sans", "placeholder", { size: "sm" }),
-  };
-
-  const inactivePaneActiveTab = {
-    ...activePaneInactiveTab,
-    text: text(theme, "sans", "placeholder", { size: "sm" }),
-  }
-
   const titlebarPadding = 6;
 
   return {
@@ -74,22 +29,7 @@ export default function workspace(theme: Theme) {
     },
     leaderBorderOpacity: 0.7,
     leaderBorderWidth: 2.0,
-    activePaneActiveTab,
-    activePaneInactiveTab,
-    inactivePaneActiveTab,
-    inactivePaneInactiveTab,
-    paneButton: {
-      color: iconColor(theme, "secondary"),
-      border: {
-        ...activePaneActiveTab.border,
-      },
-      iconWidth: 12,
-      buttonWidth: activePaneActiveTab.height,
-      hover: {
-        color: iconColor(theme, "active"),
-        background: backgroundColor(theme, 300),
-      },
-    },
+    tabBar: tabBar(theme),
     modal: {
       margin: {
         bottom: 52,

styles/src/themes/common/base16.ts 🔗

@@ -130,8 +130,8 @@ export function createTheme(
   const textColor = {
     primary: sample(ramps.neutral, 6),
     secondary: sample(ramps.neutral, 5),
-    muted: sample(ramps.neutral, 5),
-    placeholder: sample(ramps.neutral, 4),
+    muted: sample(ramps.neutral, 4),
+    placeholder: sample(ramps.neutral, 3),
     active: sample(ramps.neutral, 7),
     feature: sample(ramps.blue, 0.5),
     ok: sample(ramps.green, 0.5),