Detailed changes
@@ -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()
}
@@ -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)]
@@ -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())
@@ -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),
+ },
+ },
+ }
+}
@@ -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,
@@ -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),