diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 792d970fcd..0a32a8427b 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/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() } diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index f7c470bb96..349a505a08 100644 --- a/crates/theme/src/theme.rs +++ b/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, + 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, + 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)] diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 1b96cd9a12..7ba8badc9d 100644 --- a/crates/workspace/src/pane.rs +++ b/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::(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::().theme.workspace; + let theme = + &cx.global::().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::() - .theme - .workspace - .active_pane_active_tab - .height, - ) + .with_height(cx.global::().theme.workspace.tab_bar.height) .boxed() }) .with_child(ChildView::new(&self.toolbar).boxed()) diff --git a/styles/src/styleTree/tabBar.ts b/styles/src/styleTree/tabBar.ts new file mode 100644 index 0000000000..d35af34ac9 --- /dev/null +++ b/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), + }, + }, + } +} \ No newline at end of file diff --git a/styles/src/styleTree/workspace.ts b/styles/src/styleTree/workspace.ts index c86dce7226..4937edfdee 100644 --- a/styles/src/styleTree/workspace.ts +++ b/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, diff --git a/styles/src/themes/common/base16.ts b/styles/src/themes/common/base16.ts index 321184d40d..7aa72ef137 100644 --- a/styles/src/themes/common/base16.ts +++ b/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),