flattened layers and elevations

K Simmons created

Change summary

Cargo.lock                                        |  16 --
crates/theme/src/theme.rs                         |  18 -
crates/theme_testbench/src/theme_testbench.rs     | 109 +++-------------
styles/src/styleTree/app.ts                       |  70 ++--------
styles/src/styleTree/commandPalette.ts            |   2 
styles/src/styleTree/contactFinder.ts             |   2 
styles/src/styleTree/contactList.ts               |   2 
styles/src/styleTree/contactNotification.ts       |   2 
styles/src/styleTree/contactsPopover.ts           |   4 
styles/src/styleTree/contextMenu.ts               |   5 
styles/src/styleTree/editor.ts                    |  97 +++++++-------
styles/src/styleTree/hoverPopover.ts              |  10 
styles/src/styleTree/incomingCallNotification.ts  |   2 
styles/src/styleTree/picker.ts                    |   5 
styles/src/styleTree/projectDiagnostics.ts        |   2 
styles/src/styleTree/projectPanel.ts              |   2 
styles/src/styleTree/projectSharedNotification.ts |   5 
styles/src/styleTree/search.ts                    |   2 
styles/src/styleTree/statusBar.ts                 |   2 
styles/src/styleTree/tabBar.ts                    |   7 
styles/src/styleTree/terminal.ts                  |  64 ++++----
styles/src/styleTree/tooltip.ts                   |   5 
styles/src/styleTree/updateNotification.ts        |   2 
styles/src/styleTree/workspace.ts                 |  37 ++--
styles/src/themes/common/colorScheme.ts           |  22 +--
styles/src/themes/common/ramps.ts                 | 107 ++++------------
26 files changed, 203 insertions(+), 398 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -855,22 +855,6 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
-[[package]]
-name = "chat_panel"
-version = "0.1.0"
-dependencies = [
- "client",
- "editor",
- "gpui",
- "menu",
- "postage",
- "settings",
- "theme",
- "time 0.3.15",
- "util",
- "workspace",
-]
-
 [[package]]
 name = "chrono"
 version = "0.4.22"

crates/theme/src/theme.rs 🔗

@@ -797,22 +797,16 @@ pub struct ColorScheme {
     pub name: String,
     pub is_light: bool,
 
-    pub lowest: Elevation,
-    pub middle: Elevation,
-    pub highest: Elevation,
-
-    pub players: Vec<Player>,
-}
-
-#[derive(Clone, Deserialize, Default)]
-pub struct Elevation {
     pub ramps: RampSet,
 
-    pub bottom: Layer,
+    pub lowest: Layer,
     pub middle: Layer,
-    pub top: Layer,
+    pub highest: Layer,
+
+    pub popover_shadow: Shadow,
+    pub modal_shadow: Shadow,
 
-    pub shadow: Option<Shadow>,
+    pub players: Vec<Player>,
 }
 
 #[derive(Clone, Deserialize, Default)]

crates/theme_testbench/src/theme_testbench.rs 🔗

@@ -11,7 +11,7 @@ use gpui::{
 use project::{Project, ProjectEntryId, ProjectPath};
 use settings::Settings;
 use smallvec::SmallVec;
-use theme::{ColorScheme, Elevation, Layer, Style, StyleSet};
+use theme::{ColorScheme, Layer, Style, StyleSet};
 use workspace::{Item, Workspace};
 
 actions!(theme, [DeployThemeTestbench]);
@@ -51,38 +51,15 @@ impl ThemeTestbench {
         }
 
         Flex::column()
-            .with_child(display_ramp(&color_scheme.lowest.ramps.neutral))
-            .with_child(display_ramp(&color_scheme.lowest.ramps.red))
-            .with_child(display_ramp(&color_scheme.lowest.ramps.orange))
-            .with_child(display_ramp(&color_scheme.lowest.ramps.yellow))
-            .with_child(display_ramp(&color_scheme.lowest.ramps.green))
-            .with_child(display_ramp(&color_scheme.lowest.ramps.cyan))
-            .with_child(display_ramp(&color_scheme.lowest.ramps.blue))
-            .with_child(display_ramp(&color_scheme.lowest.ramps.violet))
-            .with_child(display_ramp(&color_scheme.lowest.ramps.magenta))
-    }
-
-    fn render_elevation(
-        elevation_index: usize,
-        elevation: &Elevation,
-        cx: &mut RenderContext<'_, Self>,
-    ) -> Flex {
-        Flex::column()
-            .with_child(
-                Self::render_layer(elevation_index * 1000 + 100, &elevation.bottom, cx)
-                    .flex(1., true)
-                    .boxed(),
-            )
-            .with_child(
-                Self::render_layer(elevation_index * 1000 + 200, &elevation.middle, cx)
-                    .flex(1., true)
-                    .boxed(),
-            )
-            .with_child(
-                Self::render_layer(elevation_index * 1000 + 300, &elevation.top, cx)
-                    .flex(1., true)
-                    .boxed(),
-            )
+            .with_child(display_ramp(&color_scheme.ramps.neutral))
+            .with_child(display_ramp(&color_scheme.ramps.red))
+            .with_child(display_ramp(&color_scheme.ramps.orange))
+            .with_child(display_ramp(&color_scheme.ramps.yellow))
+            .with_child(display_ramp(&color_scheme.ramps.green))
+            .with_child(display_ramp(&color_scheme.ramps.cyan))
+            .with_child(display_ramp(&color_scheme.ramps.blue))
+            .with_child(display_ramp(&color_scheme.ramps.violet))
+            .with_child(display_ramp(&color_scheme.ramps.magenta))
     }
 
     fn render_layer(
@@ -272,44 +249,6 @@ impl ThemeTestbench {
 
         Label::new(text, text_style)
     }
-
-    fn elevation_style(elevation: &Elevation) -> ContainerStyle {
-        let style = ContainerStyle {
-            margin: Margin {
-                top: 10.,
-                bottom: 10.,
-                left: 10.,
-                right: 10.,
-            },
-            background_color: Some(elevation.bottom.base.default.background),
-            ..Default::default()
-        };
-
-        if elevation.shadow.is_some() {
-            ContainerStyle {
-                padding: Padding {
-                    top: 10.,
-                    bottom: 10.,
-                    left: 10.,
-                    right: 10.,
-                },
-                border: Border {
-                    width: 1.,
-                    color: elevation.bottom.base.default.border,
-                    overlay: false,
-                    top: true,
-                    bottom: true,
-                    left: true,
-                    right: true,
-                },
-                corner_radius: 32.,
-                shadow: elevation.shadow,
-                ..style
-            }
-        } else {
-            style
-        }
-    }
 }
 
 impl Entity for ThemeTestbench {
@@ -333,32 +272,24 @@ impl View for ThemeTestbench {
                     .boxed(),
             )
             .with_child(
-                Self::render_elevation(0, &color_scheme.lowest, cx)
-                    .flex(1., true)
-                    .boxed(),
-            )
-            .with_child(
-                Flex::row()
+                Flex::column()
                     .with_child(
-                        Self::render_elevation(1, &color_scheme.middle, cx)
+                        Self::render_layer(100, &color_scheme.lowest, cx)
                             .flex(1., true)
                             .boxed(),
                     )
                     .with_child(
-                        Container::new(
-                            Self::render_elevation(2, &color_scheme.highest, cx).boxed(),
-                        )
-                        .with_style(Self::elevation_style(&color_scheme.highest))
-                        .flex(1., true)
-                        .boxed(),
+                        Self::render_layer(200, &color_scheme.middle, cx)
+                            .flex(1., true)
+                            .boxed(),
+                    )
+                    .with_child(
+                        Self::render_layer(300, &color_scheme.highest, cx)
+                            .flex(1., true)
+                            .boxed(),
                     )
-                    .contained()
-                    .with_style(Self::elevation_style(&color_scheme.middle))
-                    .flex(2., true)
                     .boxed(),
             )
-            .contained()
-            .with_style(Self::elevation_style(&color_scheme.lowest))
             .boxed()
     }
 }

styles/src/styleTree/app.ts 🔗

@@ -18,10 +18,6 @@ import contactList from "./contactList";
 import incomingCallNotification from "./incomingCallNotification";
 import { ColorScheme } from "../themes/common/colorScheme";
 
-// export const panel = {
-//   padding: { top: 12, bottom: 12 },
-// };
-
 export default function app(colorScheme: ColorScheme): Object {
   return {
     meta: {
@@ -43,68 +39,28 @@ export default function app(colorScheme: ColorScheme): Object {
     contactList: contactList(colorScheme),
     search: search(colorScheme),
     breadcrumbs: {
-      ...text(colorScheme.lowest.top, "sans", "variant"),
+      ...text(colorScheme.highest, "sans", "variant"),
       padding: {
         left: 6,
       },
     },
     updateNotification: updateNotification(colorScheme),
     tooltip: tooltip(colorScheme),
-    terminal: terminal(colorScheme.lowest, colorScheme.players[0].cursor),
+    terminal: terminal(colorScheme),
     colorScheme: {
       ...colorScheme,
-      lowest: {
-        ...colorScheme.lowest,
-        ramps: {
-          neutral: colorScheme.lowest.ramps.neutral.colors(100, "hex"),
-          red: colorScheme.lowest.ramps.red.colors(100, "hex"),
-          orange: colorScheme.lowest.ramps.orange.colors(100, "hex"),
-          yellow: colorScheme.lowest.ramps.yellow.colors(100, "hex"),
-          green: colorScheme.lowest.ramps.green.colors(100, "hex"),
-          cyan: colorScheme.lowest.ramps.cyan.colors(100, "hex"),
-          blue: colorScheme.lowest.ramps.blue.colors(100, "hex"),
-          violet: colorScheme.lowest.ramps.violet.colors(100, "hex"),
-          magenta: colorScheme.lowest.ramps.magenta.colors(100, "hex"),
-        },
-      },
-      middle: {
-        ...colorScheme.middle,
-        ramps: {
-          neutral: colorScheme.middle.ramps.neutral.colors(100, "hex"),
-          red: colorScheme.middle.ramps.red.colors(100, "hex"),
-          orange: colorScheme.middle.ramps.orange.colors(100, "hex"),
-          yellow: colorScheme.middle.ramps.yellow.colors(100, "hex"),
-          green: colorScheme.middle.ramps.green.colors(100, "hex"),
-          cyan: colorScheme.middle.ramps.cyan.colors(100, "hex"),
-          blue: colorScheme.middle.ramps.blue.colors(100, "hex"),
-          violet: colorScheme.middle.ramps.violet.colors(100, "hex"),
-          magenta: colorScheme.middle.ramps.magenta.colors(100, "hex"),
-        },
-      },
-      highest: {
-        ...colorScheme.highest,
-        ramps: {
-          neutral: colorScheme.highest.ramps.neutral.colors(100, "hex"),
-          red: colorScheme.highest.ramps.red.colors(100, "hex"),
-          orange: colorScheme.highest.ramps.orange.colors(100, "hex"),
-          yellow: colorScheme.highest.ramps.yellow.colors(100, "hex"),
-          green: colorScheme.highest.ramps.green.colors(100, "hex"),
-          cyan: colorScheme.highest.ramps.cyan.colors(100, "hex"),
-          blue: colorScheme.highest.ramps.blue.colors(100, "hex"),
-          violet: colorScheme.highest.ramps.violet.colors(100, "hex"),
-          magenta: colorScheme.highest.ramps.magenta.colors(100, "hex"),
-        },
+      players: Object.values(colorScheme.players),
+      ramps: {
+        neutral: colorScheme.ramps.neutral.colors(100, "hex"),
+        red: colorScheme.ramps.red.colors(100, "hex"),
+        orange: colorScheme.ramps.orange.colors(100, "hex"),
+        yellow: colorScheme.ramps.yellow.colors(100, "hex"),
+        green: colorScheme.ramps.green.colors(100, "hex"),
+        cyan: colorScheme.ramps.cyan.colors(100, "hex"),
+        blue: colorScheme.ramps.blue.colors(100, "hex"),
+        violet: colorScheme.ramps.violet.colors(100, "hex"),
+        magenta: colorScheme.ramps.magenta.colors(100, "hex"),
       },
-      players: [
-        colorScheme.players["0"],
-        colorScheme.players["1"],
-        colorScheme.players["2"],
-        colorScheme.players["3"],
-        colorScheme.players["4"],
-        colorScheme.players["5"],
-        colorScheme.players["6"],
-        colorScheme.players["7"],
-      ],
     },
   };
 }

styles/src/styleTree/commandPalette.ts 🔗

@@ -3,7 +3,7 @@ import { withOpacity } from "../utils/color";
 import { text, background } from "./components";
 
 export default function commandPalette(colorScheme: ColorScheme) {
-  let layer = colorScheme.highest.top;
+  let layer = colorScheme.highest;
   return {
     keystrokeSpacing: 8,
     key: {

styles/src/styleTree/contactFinder.ts 🔗

@@ -3,7 +3,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, foreground, text } from "./components";
 
 export default function contactFinder(colorScheme: ColorScheme) {
-  let layer = colorScheme.highest.top;
+  let layer = colorScheme.highest;
 
   const sideMargin = 6;
   const contactButton = {

styles/src/styleTree/contactList.ts 🔗

@@ -11,7 +11,7 @@ export default function contactsPanel(colorScheme: ColorScheme) {
   const nameMargin = 8;
   const sidePadding = 12;
 
-  let layer = colorScheme.lowest.middle;
+  let layer = colorScheme.middle;
 
   const contactButton = {
     background: background(layer, "on"),

styles/src/styleTree/contactNotification.ts 🔗

@@ -5,7 +5,7 @@ const avatarSize = 12;
 const headerPadding = 8;
 
 export default function contactNotification(colorScheme: ColorScheme): Object {
-  let layer = colorScheme.middle.bottom;
+  let layer = colorScheme.lowest;
   return {
     headerAvatar: {
       height: avatarSize,

styles/src/styleTree/contactsPopover.ts 🔗

@@ -2,14 +2,14 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, text } from "./components";
 
 export default function contactsPopover(colorScheme: ColorScheme) {
-  let layer = colorScheme.middle.middle;
+  let layer = colorScheme.middle;
   const sidePadding = 12;
   return {
     background: background(layer),
     cornerRadius: 6,
     padding: { top: 6 },
     margin: { top: -6 },
-    shadow: colorScheme.middle.shadow,
+    shadow: colorScheme.popoverShadow,
     border: border(layer),
     width: 300,
     height: 400,

styles/src/styleTree/contextMenu.ts 🔗

@@ -2,13 +2,12 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, borderColor, text } from "./components";
 
 export default function contextMenu(colorScheme: ColorScheme) {
-  let elevation = colorScheme.middle;
-  let layer = elevation.bottom;
+  let layer = colorScheme.lowest;
   return {
     background: background(layer),
     cornerRadius: 10,
     padding: 4,
-    shadow: elevation.shadow,
+    shadow: colorScheme.popoverShadow,
     border: border(layer),
     keystrokeMargin: 30,
     item: {

styles/src/styleTree/editor.ts 🔗

@@ -15,8 +15,7 @@ import {
 import hoverPopover from "./hoverPopover";
 
 export default function editor(colorScheme: ColorScheme) {
-  let elevation = colorScheme.lowest;
-  let layer = elevation.top;
+  let layer = colorScheme.highest;
 
   const autocompleteItem = {
     cornerRadius: 6,
@@ -48,88 +47,88 @@ export default function editor(colorScheme: ColorScheme) {
 
   const syntax = {
     primary: {
-      color: elevation.ramps.neutral(1).hex(),
+      color: colorScheme.ramps.neutral(1).hex(),
       weight: fontWeights.normal,
     },
     comment: {
-      color: elevation.ramps.neutral(0.71).hex(),
+      color: colorScheme.ramps.neutral(0.71).hex(),
       weight: fontWeights.normal,
     },
     punctuation: {
-      color: elevation.ramps.neutral(0.86).hex(),
+      color: colorScheme.ramps.neutral(0.86).hex(),
       weight: fontWeights.normal,
     },
     constant: {
-      color: elevation.ramps.green(0.5).hex(),
+      color: colorScheme.ramps.green(0.5).hex(),
       weight: fontWeights.normal,
     },
     keyword: {
-      color: elevation.ramps.blue(0.5).hex(),
+      color: colorScheme.ramps.blue(0.5).hex(),
       weight: fontWeights.normal,
     },
     function: {
-      color: elevation.ramps.yellow(0.5).hex(),
+      color: colorScheme.ramps.yellow(0.5).hex(),
       weight: fontWeights.normal,
     },
     type: {
-      color: elevation.ramps.cyan(0.5).hex(),
+      color: colorScheme.ramps.cyan(0.5).hex(),
       weight: fontWeights.normal,
     },
     constructor: {
-      color: elevation.ramps.blue(0.5).hex(),
+      color: colorScheme.ramps.blue(0.5).hex(),
       weight: fontWeights.normal,
     },
     variant: {
-      color: elevation.ramps.blue(0.5).hex(),
+      color: colorScheme.ramps.blue(0.5).hex(),
       weight: fontWeights.normal,
     },
     property: {
-      color: elevation.ramps.blue(0.5).hex(),
+      color: colorScheme.ramps.blue(0.5).hex(),
       weight: fontWeights.normal,
     },
     enum: {
-      color: elevation.ramps.orange(0.5).hex(),
+      color: colorScheme.ramps.orange(0.5).hex(),
       weight: fontWeights.normal,
     },
     operator: {
-      color: elevation.ramps.orange(0.5).hex(),
+      color: colorScheme.ramps.orange(0.5).hex(),
       weight: fontWeights.normal,
     },
     string: {
-      color: elevation.ramps.orange(0.5).hex(),
+      color: colorScheme.ramps.orange(0.5).hex(),
       weight: fontWeights.normal,
     },
     number: {
-      color: elevation.ramps.green(0.5).hex(),
+      color: colorScheme.ramps.green(0.5).hex(),
       weight: fontWeights.normal,
     },
     boolean: {
-      color: elevation.ramps.green(0.5).hex(),
+      color: colorScheme.ramps.green(0.5).hex(),
       weight: fontWeights.normal,
     },
     predictive: {
-      color: elevation.ramps.neutral(0.57).hex(),
+      color: colorScheme.ramps.neutral(0.57).hex(),
       weight: fontWeights.normal,
     },
     title: {
-      color: elevation.ramps.yellow(0.5).hex(),
+      color: colorScheme.ramps.yellow(0.5).hex(),
       weight: fontWeights.bold,
     },
     emphasis: {
-      color: elevation.ramps.blue(0.5).hex(),
+      color: colorScheme.ramps.blue(0.5).hex(),
       weight: fontWeights.normal,
     },
     "emphasis.strong": {
-      color: elevation.ramps.blue(0.5).hex(),
+      color: colorScheme.ramps.blue(0.5).hex(),
       weight: fontWeights.bold,
     },
     linkUri: {
-      color: elevation.ramps.green(0.5).hex(),
+      color: colorScheme.ramps.green(0.5).hex(),
       weight: fontWeights.normal,
       underline: true,
     },
     linkText: {
-      color: elevation.ramps.orange(0.5).hex(),
+      color: colorScheme.ramps.orange(0.5).hex(),
       weight: fontWeights.normal,
       italic: true,
     },
@@ -152,11 +151,11 @@ export default function editor(colorScheme: ColorScheme) {
       widthEm: 0.16,
       cornerRadius: 0.05,
     },
-    documentHighlightReadBackground: elevation.ramps
+    documentHighlightReadBackground: colorScheme.ramps
       .neutral(0.5)
       .alpha(0.2)
       .hex(), // TODO: This was blend
-    documentHighlightWriteBackground: elevation.ramps
+    documentHighlightWriteBackground: colorScheme.ramps
       .neutral(0.5)
       .alpha(0.4)
       .hex(), // TODO: This was blend * 2
@@ -178,67 +177,69 @@ export default function editor(colorScheme: ColorScheme) {
       colorScheme.players[7],
     ],
     autocomplete: {
-      background: background(elevation.bottom),
+      background: background(colorScheme.lowest),
       cornerRadius: 8,
       padding: 4,
       margin: {
         left: -14,
       },
-      border: border(elevation.bottom),
-      shadow: elevation.above.shadow,
-      matchHighlight: elevation.above.ramps.blue(0.5).hex(),
+      border: border(colorScheme.lowest),
+      shadow: colorScheme.popoverShadow,
+      matchHighlight: foreground(colorScheme.lowest, "accent"),
       item: autocompleteItem,
       hoveredItem: {
         ...autocompleteItem,
-        background: background(elevation.bottom, "hovered"),
+        matchHighlight: foreground(colorScheme.lowest, "accent", "hovered"),
+        background: background(colorScheme.lowest, "hovered"),
       },
       selectedItem: {
         ...autocompleteItem,
-        background: background(elevation.bottom, "active"),
+        matchHighlight: foreground(colorScheme.lowest, "accent", "active"),
+        background: background(colorScheme.lowest, "active"),
       },
     },
     diagnosticHeader: {
-      background: background(elevation.middle),
+      background: background(colorScheme.middle),
       iconWidthFactor: 1.5,
       textScaleFactor: 0.857,
-      border: border(elevation.middle, {
+      border: border(colorScheme.middle, {
         bottom: true,
         top: true,
       }),
       code: {
-        ...text(elevation.middle, "mono", { size: "sm" }),
+        ...text(colorScheme.middle, "mono", { size: "sm" }),
         margin: {
           left: 10,
         },
       },
       message: {
-        highlightText: text(elevation.middle, "sans", {
+        highlightText: text(colorScheme.middle, "sans", {
           size: "sm",
           weight: "bold",
         }),
-        text: text(elevation.middle, "sans", { size: "sm" }),
+        text: text(colorScheme.middle, "sans", { size: "sm" }),
       },
     },
     diagnosticPathHeader: {
-      background: background(elevation.middle),
+      background: background(colorScheme.middle),
       textScaleFactor: 0.857,
-      filename: text(elevation.middle, "mono", { size: "sm" }),
+      filename: text(colorScheme.middle, "mono", { size: "sm" }),
       path: {
-        ...text(elevation.middle, "mono", { size: "sm" }),
+        ...text(colorScheme.middle, "mono", { size: "sm" }),
         margin: {
           left: 12,
         },
       },
     },
-    errorDiagnostic: diagnostic(elevation.middle, "negative"),
-    warningDiagnostic: diagnostic(elevation.middle, "warning"),
-    informationDiagnostic: diagnostic(elevation.middle, "accent"),
-    hintDiagnostic: diagnostic(elevation.middle, "warning"),
-    invalidErrorDiagnostic: diagnostic(elevation.middle, "base"),
-    invalidHintDiagnostic: diagnostic(elevation.middle, "base"),
-    invalidInformationDiagnostic: diagnostic(elevation.middle, "base"),
-    invalidWarningDiagnostic: diagnostic(elevation.middle, "base"),
-    hoverPopover: hoverPopover(elevation.above),
+    errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
+    warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
+    informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
+    hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
+    invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
+    invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
+    invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
+    invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
+    hoverPopover: hoverPopover(colorScheme),
     linkDefinition: {
       color: syntax.linkUri.color,
       underline: syntax.linkUri.underline,

styles/src/styleTree/hoverPopover.ts 🔗

@@ -1,8 +1,8 @@
-import { Elevation } from "../themes/common/colorScheme";
+import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, text } from "./components";
 
-export default function HoverPopover(elevation: Elevation) {
-  let layer = elevation.middle;
+export default function HoverPopover(colorScheme: ColorScheme) {
+  let layer = colorScheme.middle;
   let baseContainer = {
     background: background(layer),
     cornerRadius: 8,
@@ -12,7 +12,7 @@ export default function HoverPopover(elevation: Elevation) {
       top: 4,
       bottom: 4,
     },
-    shadow: elevation.shadow,
+    shadow: colorScheme.popoverShadow,
     border: border(layer),
     margin: {
       left: -8,
@@ -40,6 +40,6 @@ export default function HoverPopover(elevation: Elevation) {
       padding: { top: 4 },
     },
     prose: text(layer, "sans", { size: "sm" }),
-    highlight: elevation.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better
+    highlight: colorScheme.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better
   };
 }

styles/src/styleTree/incomingCallNotification.ts 🔗

@@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, text } from "./components";
 
 export default function incomingCallNotification(colorScheme: ColorScheme): Object {
-  let layer = colorScheme.middle.middle;
+  let layer = colorScheme.middle;
   const avatarSize = 48;
   return {
     windowHeight: 74,

styles/src/styleTree/picker.ts 🔗

@@ -2,12 +2,11 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, text } from "./components";
 
 export default function picker(colorScheme: ColorScheme) {
-  let elevation = colorScheme.highest;
-  let layer = elevation.top;
+  let layer = colorScheme.highest;
   return {
     background: background(layer),
     border: border(layer),
-    shadow: elevation.shadow,
+    shadow: colorScheme.modalShadow,
     cornerRadius: 12,
     padding: {
       bottom: 4,

styles/src/styleTree/projectDiagnostics.ts 🔗

@@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, text } from "./components";
 
 export default function projectDiagnostics(colorScheme: ColorScheme) {
-  let layer = colorScheme.lowest.top;
+  let layer = colorScheme.highest;
   return {
     background: background(layer),
     tabIconSpacing: 4,

styles/src/styleTree/projectPanel.ts 🔗

@@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, foreground, text } from "./components";
 
 export default function projectPanel(colorScheme: ColorScheme) {
-  let layer = colorScheme.lowest.middle;
+  let layer = colorScheme.middle;
   return {
     background: background(layer),
     padding: { left: 12, right: 12, top: 6, bottom: 6 },

styles/src/styleTree/projectSharedNotification.ts 🔗

@@ -2,14 +2,13 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, text } from "./components";
 
 export default function projectSharedNotification(colorScheme: ColorScheme): Object {
-  let elevation = colorScheme.middle;
-  let layer = elevation.middle;
+  let layer = colorScheme.middle;
 
   const avatarSize = 48;
   return {
     windowHeight: 74,
     windowWidth: 380,
-    background: background(layer,),
+    background: background(layer),
     ownerContainer: {
       padding: 12,
     },

styles/src/styleTree/search.ts 🔗

@@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, text } from "./components";
 
 export default function search(colorScheme: ColorScheme) {
-  let layer = colorScheme.lowest.top;
+  let layer = colorScheme.highest;
 
   // Search input
   const editor = {

styles/src/styleTree/statusBar.ts 🔗

@@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, foreground, text } from "./components";
 
 export default function statusBar(colorScheme: ColorScheme) {
-  let layer = colorScheme.lowest.bottom;
+  let layer = colorScheme.lowest;
 
   const statusContainer = {
     cornerRadius: 6,

styles/src/styleTree/tabBar.ts 🔗

@@ -5,9 +5,8 @@ import { text, border, background, foreground } from "./components";
 export default function tabBar(colorScheme: ColorScheme) {
   const height = 32;
 
-  let elevation = colorScheme.lowest;
-  let activeLayer = elevation.top;
-  let layer = elevation.middle;
+  let activeLayer = colorScheme.highest;
+  let layer = colorScheme.middle;
 
   const tab = {
     height,
@@ -70,7 +69,7 @@ export default function tabBar(colorScheme: ColorScheme) {
     ...activePaneActiveTab,
     background: withOpacity(tab.background, 0.95),
     border: undefined as any,
-    shadow: elevation.above.shadow,
+    shadow: colorScheme.popoverShadow,
   };
 
   return {

styles/src/styleTree/terminal.ts 🔗

@@ -1,6 +1,6 @@
-import { Elevation } from "../themes/common/colorScheme";
+import { ColorScheme } from "../themes/common/colorScheme";
 
-export default function terminal(elevation: Elevation, cursor_color: string) {
+export default function terminal(colorScheme: ColorScheme) {
   /**
    * Colors are controlled per-cell in the terminal grid.
    * Cells can be set to any of these more 'theme-capable' colors
@@ -9,44 +9,44 @@ export default function terminal(elevation: Elevation, cursor_color: string) {
    * https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
    */
   return {
-    black: elevation.ramps.neutral(0).hex(),
-    red: elevation.ramps.red(0.5).hex(),
-    green: elevation.ramps.green(0.5).hex(),
-    yellow: elevation.ramps.yellow(0.5).hex(),
-    blue: elevation.ramps.blue(0.5).hex(),
-    magenta: elevation.ramps.magenta(0.5).hex(),
-    cyan: elevation.ramps.cyan(0.5).hex(),
-    white: elevation.ramps.neutral(1).hex(),
-    brightBlack: elevation.ramps.neutral(0.4).hex(),
-    brightRed: elevation.ramps.red(0.25).hex(),
-    brightGreen: elevation.ramps.green(0.25).hex(),
-    brightYellow: elevation.ramps.yellow(0.25).hex(),
-    brightBlue: elevation.ramps.blue(0.25).hex(),
-    brightMagenta: elevation.ramps.magenta(0.25).hex(),
-    brightCyan: elevation.ramps.cyan(0.25).hex(),
-    brightWhite: elevation.ramps.neutral(1).hex(),
+    black: colorScheme.ramps.neutral(0).hex(),
+    red: colorScheme.ramps.red(0.5).hex(),
+    green: colorScheme.ramps.green(0.5).hex(),
+    yellow: colorScheme.ramps.yellow(0.5).hex(),
+    blue: colorScheme.ramps.blue(0.5).hex(),
+    magenta: colorScheme.ramps.magenta(0.5).hex(),
+    cyan: colorScheme.ramps.cyan(0.5).hex(),
+    white: colorScheme.ramps.neutral(1).hex(),
+    brightBlack: colorScheme.ramps.neutral(0.4).hex(),
+    brightRed: colorScheme.ramps.red(0.25).hex(),
+    brightGreen: colorScheme.ramps.green(0.25).hex(),
+    brightYellow: colorScheme.ramps.yellow(0.25).hex(),
+    brightBlue: colorScheme.ramps.blue(0.25).hex(),
+    brightMagenta: colorScheme.ramps.magenta(0.25).hex(),
+    brightCyan: colorScheme.ramps.cyan(0.25).hex(),
+    brightWhite: colorScheme.ramps.neutral(1).hex(),
     /**
      * Default color for characters
      */
-    foreground: elevation.ramps.neutral(1).hex(),
+    foreground: colorScheme.ramps.neutral(1).hex(),
     /**
      * Default color for the rectangle background of a cell
      */
-    background: elevation.ramps.neutral(0).hex(),
-    modalBackground: elevation.ramps.neutral(0.1).hex(),
+    background: colorScheme.ramps.neutral(0).hex(),
+    modalBackground: colorScheme.ramps.neutral(0.1).hex(),
     /**
      * Default color for the cursor
      */
-    cursor: cursor_color,
-    dimBlack: elevation.ramps.neutral(1).hex(),
-    dimRed: elevation.ramps.red(0.75).hex(),
-    dimGreen: elevation.ramps.green(0.75).hex(),
-    dimYellow: elevation.ramps.yellow(0.75).hex(),
-    dimBlue: elevation.ramps.blue(0.75).hex(),
-    dimMagenta: elevation.ramps.magenta(0.75).hex(),
-    dimCyan: elevation.ramps.cyan(0.75).hex(),
-    dimWhite: elevation.ramps.neutral(0.6).hex(),
-    brightForeground: elevation.ramps.neutral(1).hex(),
-    dimForeground: elevation.ramps.neutral(0).hex(),
+    cursor: colorScheme.players[0].cursor,
+    dimBlack: colorScheme.ramps.neutral(1).hex(),
+    dimRed: colorScheme.ramps.red(0.75).hex(),
+    dimGreen: colorScheme.ramps.green(0.75).hex(),
+    dimYellow: colorScheme.ramps.yellow(0.75).hex(),
+    dimBlue: colorScheme.ramps.blue(0.75).hex(),
+    dimMagenta: colorScheme.ramps.magenta(0.75).hex(),
+    dimCyan: colorScheme.ramps.cyan(0.75).hex(),
+    dimWhite: colorScheme.ramps.neutral(0.6).hex(),
+    brightForeground: colorScheme.ramps.neutral(1).hex(),
+    dimForeground: colorScheme.ramps.neutral(0).hex(),
   };
 }

styles/src/styleTree/tooltip.ts 🔗

@@ -2,14 +2,13 @@ import { ColorScheme } from "../themes/common/colorScheme";
 import { background, border, text } from "./components";
 
 export default function tooltip(colorScheme: ColorScheme) {
-  let elevation = colorScheme.middle;
-  let layer = colorScheme.middle.middle;
+  let layer = colorScheme.middle;
   return {
     background: background(layer),
     border: border(layer),
     padding: { top: 4, bottom: 4, left: 8, right: 8 },
     margin: { top: 6, left: 6 },
-    shadow: elevation.shadow,
+    shadow: colorScheme.popoverShadow,
     cornerRadius: 6,
     text: text(layer, "sans", { size: "xs" }),
     keystroke: {

styles/src/styleTree/updateNotification.ts 🔗

@@ -4,7 +4,7 @@ import { foreground, text } from "./components";
 const headerPadding = 8;
 
 export default function updateNotification(colorScheme: ColorScheme): Object {
-  let layer = colorScheme.middle.middle;
+  let layer = colorScheme.middle;
   return {
     message: {
       ...text(layer, "sans", { size: "xs" }),

styles/src/styleTree/workspace.ts 🔗

@@ -11,8 +11,7 @@ import statusBar from "./statusBar";
 import tabBar from "./tabBar";
 
 export default function workspace(colorScheme: ColorScheme) {
-  const elevation = colorScheme.lowest;
-  const layer = elevation.bottom;
+  const layer = colorScheme.lowest;
   const titlebarPadding = 6;
   const titlebarButton = {
     cornerRadius: 6,
@@ -28,7 +27,7 @@ export default function workspace(colorScheme: ColorScheme) {
     hover: {
       ...text(layer, "sans", "hovered", { size: "xs" }),
       background: background(layer, "hovered"),
-      border: border(elevation.top, "hovered"),
+      border: border(layer, "hovered"),
     },
   };
   const avatarWidth = 18;
@@ -44,12 +43,12 @@ export default function workspace(colorScheme: ColorScheme) {
       ...text(layer, "sans", { size: "lg" }),
     },
     externalLocationMessage: {
-      background: background(elevation.middle, "accent"),
-      border: border(elevation.middle, "accent"),
+      background: background(colorScheme.middle, "accent"),
+      border: border(colorScheme.middle, "accent"),
       cornerRadius: 6,
       padding: 12,
       margin: { bottom: 8, right: 8 },
-      ...text(elevation.middle, "sans", "accent", { size: "xs" }),
+      ...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
     },
     leaderBorderOpacity: 0.7,
     leaderBorderWidth: 2.0,
@@ -166,20 +165,20 @@ export default function workspace(colorScheme: ColorScheme) {
 
     toolbar: {
       height: 34,
-      background: background(elevation.top),
-      border: border(elevation.top, { bottom: true }),
+      background: background(colorScheme.highest),
+      border: border(colorScheme.highest, { bottom: true }),
       itemSpacing: 8,
       navButton: {
-        color: foreground(elevation.top, "on"),
+        color: foreground(colorScheme.highest, "on"),
         iconWidth: 12,
         buttonWidth: 24,
         cornerRadius: 6,
         hover: {
-          color: foreground(elevation.top, "on", "hovered"),
-          background: background(elevation.top, "on", "hovered"),
+          color: foreground(colorScheme.highest, "on", "hovered"),
+          background: background(colorScheme.highest, "on", "hovered"),
         },
         disabled: {
-          color: foreground(elevation.top, "on", "disabled"),
+          color: foreground(colorScheme.highest, "on", "disabled"),
         },
       },
       padding: { left: 8, right: 8, top: 4, bottom: 4 },
@@ -194,11 +193,11 @@ export default function workspace(colorScheme: ColorScheme) {
     },
     notification: {
       margin: { top: 10 },
-      background: background(elevation.above.middle),
+      background: background(colorScheme.middle),
       cornerRadius: 6,
       padding: 12,
-      border: border(elevation.above.middle),
-      shadow: elevation.above.shadow,
+      border: border(colorScheme.middle),
+      shadow: colorScheme.popoverShadow,
     },
     notifications: {
       width: 400,
@@ -207,14 +206,14 @@ export default function workspace(colorScheme: ColorScheme) {
     dock: {
       initialSizeRight: 640,
       initialSizeBottom: 480,
-      wash_color: withOpacity(background(elevation.top), 0.5),
+      wash_color: withOpacity(background(colorScheme.highest), 0.5),
       panel: {
-        border: border(elevation.top),
+        border: border(colorScheme.highest),
       },
       maximized: {
         margin: 32,
-        border: border(elevation.above.top, { overlay: true }),
-        shadow: elevation.above.shadow,
+        border: border(colorScheme.highest, { overlay: true }),
+        shadow: colorScheme.modalShadow,
       },
     },
   };

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

@@ -4,9 +4,14 @@ export interface ColorScheme {
   name: string;
   isLight: boolean;
 
-  lowest: Elevation;
-  middle: Elevation;
-  highest: Elevation;
+  lowest: Layer;
+  middle: Layer;
+  highest: Layer;
+
+  ramps: RampSet;
+
+  popoverShadow: Shadow;
+  modalShadow: Shadow;
 
   players: Players;
 }
@@ -27,17 +32,6 @@ export interface Players {
   "7": Player;
 }
 
-export interface Elevation {
-  ramps: RampSet;
-
-  bottom: Layer;
-  middle: Layer;
-  top: Layer;
-
-  above?: Elevation;
-  shadow?: Shadow;
-}
-
 export interface Shadow {
   blur: number;
   color: string;

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

@@ -1,11 +1,9 @@
 import chroma, { Color, Scale } from "chroma-js";
 import {
   ColorScheme,
-  Elevation,
   Layer,
   Player,
   RampSet,
-  Shadow,
   Style,
   Styles,
   StyleSet,
@@ -23,7 +21,7 @@ export function createColorScheme(
   colorRamps: { [rampName: string]: Scale }
 ): ColorScheme {
   // Chromajs scales from 0 to 1 flipped if isLight is true
-  let baseRamps: typeof colorRamps = {};
+  let ramps: RampSet = {} as any;
 
   // Chromajs mutates the underlying ramp when you call domain. This causes problems because
   // we now store the ramps object in the theme so that we can pull colors out of them.
@@ -33,73 +31,66 @@ export function createColorScheme(
   // function to any in order to get the colors back out from the original ramps.
   if (isLight) {
     for (var rampName in colorRamps) {
-      baseRamps[rampName] = chroma.scale(
+      (ramps as any)[rampName] = chroma.scale(
         colorRamps[rampName].colors(100).reverse()
       );
     }
-    baseRamps.neutral = chroma.scale(colorRamps.neutral.colors(100).reverse());
+    ramps.neutral = chroma.scale(colorRamps.neutral.colors(100).reverse());
   } else {
     for (var rampName in colorRamps) {
-      baseRamps[rampName] = chroma.scale(colorRamps[rampName].colors(100));
+      (ramps as any)[rampName] = chroma.scale(colorRamps[rampName].colors(100));
     }
-    baseRamps.neutral = chroma.scale(colorRamps.neutral.colors(100));
+    ramps.neutral = chroma.scale(colorRamps.neutral.colors(100));
   }
 
-  let baseSet = {
-    neutral: baseRamps.neutral,
-    red: baseRamps.red,
-    orange: baseRamps.orange,
-    yellow: baseRamps.yellow,
-    green: baseRamps.green,
-    cyan: baseRamps.cyan,
-    blue: baseRamps.blue,
-    violet: baseRamps.violet,
-    magenta: baseRamps.magenta,
-  };
-
-  let lowest = elevation(resampleSet(baseSet, evenSamples(0, 1)));
+  let lowest = lowestLayer(ramps);
+  let middle = middleLayer(ramps);
+  let highest = highestLayer(ramps);
 
-  let middle = elevation(resampleSet(baseSet, evenSamples(0.08, 1)), {
+  let popoverShadow = {
     blur: 4,
-    color: baseSet
+    color: ramps
       .neutral(isLight ? 7 : 0)
       .darken()
       .alpha(0.2)
       .hex(), // TODO used blend previously. Replace with something else
     offset: [1, 2],
-  });
-  lowest.above = middle;
+  };
 
-  let highest = elevation(resampleSet(baseSet, evenSamples(0.16, 1)), {
+  let modalShadow = {
     blur: 16,
-    color: baseSet
+    color: ramps
       .neutral(isLight ? 7 : 0)
       .darken()
       .alpha(0.2)
       .hex(), // TODO used blend previously. Replace with something else
     offset: [0, 2],
-  });
-  middle.above = highest;
+  };
 
   let players = {
-    "0": player(baseSet.blue),
-    "1": player(baseSet.green),
-    "2": player(baseSet.magenta),
-    "3": player(baseSet.orange),
-    "4": player(baseSet.violet),
-    "5": player(baseSet.cyan),
-    "6": player(baseSet.red),
-    "7": player(baseSet.yellow),
+    "0": player(ramps.blue),
+    "1": player(ramps.green),
+    "2": player(ramps.magenta),
+    "3": player(ramps.orange),
+    "4": player(ramps.violet),
+    "5": player(ramps.cyan),
+    "6": player(ramps.red),
+    "7": player(ramps.yellow),
   };
 
   return {
     name,
     isLight,
 
+    ramps,
+
     lowest,
     middle,
     highest,
 
+    popoverShadow,
+    modalShadow,
+
     players,
   };
 }
@@ -111,47 +102,7 @@ function player(ramp: Scale): Player {
   };
 }
 
-function evenSamples(min: number, max: number): number[] {
-  return Array.from(Array(101).keys()).map(
-    (i) => (i / 100) * (max - min) + min
-  );
-}
-
-function resampleSet(ramps: RampSet, samples: number[]): RampSet {
-  return {
-    neutral: resample(ramps.neutral, samples),
-    red: resample(ramps.red, samples),
-    orange: resample(ramps.orange, samples),
-    yellow: resample(ramps.yellow, samples),
-    green: resample(ramps.green, samples),
-    cyan: resample(ramps.cyan, samples),
-    blue: resample(ramps.blue, samples),
-    violet: resample(ramps.violet, samples),
-    magenta: resample(ramps.magenta, samples),
-  };
-}
-
-function resample(scale: Scale, samples: number[]): Scale {
-  let newColors = samples.map((sample) => scale(sample));
-  return chroma.scale(newColors);
-}
-
-function elevation(
-  ramps: RampSet,
-  shadow?: Shadow
-): Elevation {
-  return {
-    ramps,
-
-    bottom: bottomLayer(ramps),
-    middle: middleLayer(ramps),
-    top: topLayer(ramps),
-
-    shadow,
-  };
-}
-
-function bottomLayer(ramps: RampSet): Layer {
+function lowestLayer(ramps: RampSet): Layer {
   return {
     base: buildStyleSet(ramps.neutral, 0.2, 1),
     variant: buildStyleSet(ramps.neutral, 0.2, 0.7),
@@ -175,7 +126,7 @@ function middleLayer(ramps: RampSet): Layer {
   };
 }
 
-function topLayer(ramps: RampSet): Layer {
+function highestLayer(ramps: RampSet): Layer {
   return {
     base: buildStyleSet(ramps.neutral, 0, 1),
     variant: buildStyleSet(ramps.neutral, 0, 0.7),