Style elevations & update styleTrees

Nate Butler and Kay Simmons created

Also rename `info` -> `accent`

Co-Authored-By: Kay Simmons <3323631+Kethku@users.noreply.github.com>

Change summary

crates/theme/src/theme.rs                     |   3 
crates/theme_testbench/src/theme_testbench.rs |  10 +
styles/src/styleTree/commandPalette.ts        |   4 
styles/src/styleTree/components.ts            |   4 
styles/src/styleTree/editor.ts                |   8 
styles/src/styleTree/hoverPopover.ts          |   4 
styles/src/styleTree/picker.ts                |   8 
styles/src/styleTree/statusBar.ts             |   2 
styles/src/styleTree/tabBar.ts                |   2 
styles/src/themes/common/colorScheme.ts       |   3 
styles/src/themes/common/ramps.ts             | 115 ++++++++++----------
11 files changed, 84 insertions(+), 79 deletions(-)

Detailed changes

crates/theme/src/theme.rs 🔗

@@ -777,7 +777,7 @@ pub struct Layer {
     pub base: StyleSet,
     pub variant: StyleSet,
     pub on: StyleSet,
-    pub info: StyleSet,
+    pub accent: StyleSet,
     pub positive: StyleSet,
     pub warning: StyleSet,
     pub negative: StyleSet,
@@ -790,6 +790,7 @@ pub struct StyleSet {
     pub disabled: Style,
     pub hovered: Style,
     pub pressed: Style,
+    pub inverted: Style,
 }
 
 #[derive(Clone, Deserialize, Default)]

crates/theme_testbench/src/theme_testbench.rs 🔗

@@ -107,7 +107,7 @@ impl ThemeTestbench {
                     .boxed(),
             )
             .with_child(
-                Self::render_button_set(3, layer_index, "info", &layer.info, cx)
+                Self::render_button_set(3, layer_index, "accent", &layer.accent, cx)
                     .flex(1., false)
                     .boxed(),
             )
@@ -187,6 +187,14 @@ impl ThemeTestbench {
                 Some(|style_set| &style_set.disabled),
                 cx,
             ))
+            .with_child(Self::render_button(
+                set_index * 6 + 5,
+                layer_index,
+                "inverted",
+                &style_set,
+                Some(|style_set| &style_set.inverted),
+                cx,
+            ))
     }
 
     fn render_button(

styles/src/styleTree/commandPalette.ts 🔗

@@ -9,7 +9,7 @@ export default function commandPalette(colorScheme: ColorScheme) {
     key: {
       text: text(layer, "mono", "on", "default", { size: "xs" }),
       cornerRadius: 2,
-      background: withOpacity(background(layer, "on"), 0.5),
+      background: background(layer, "on"),
       padding: {
         top: 1,
         bottom: 1,
@@ -22,7 +22,7 @@ export default function commandPalette(colorScheme: ColorScheme) {
         left: 2,
       },
       active: {
-        text: text(layer, "mono", "on", "active", { size: "xs" }),
+        text: text(layer, "mono", "on", "inverted", { size: "xs" }),
         background: withOpacity(background(layer, "on"), 0.2),
       },
     },

styles/src/styleTree/components.ts 🔗

@@ -6,14 +6,14 @@ function isStyleSet(key: any): key is StyleSets {
     "base",
     "variant",
     "on",
-    "info",
+    "accent",
     "positive",
     "warning",
     "negative",
   ].includes(key);
 }
 function isStyle(key: any): key is Styles {
-  return ["default", "active", "disabled", "hovered", "pressed"].includes(key);
+  return ["default", "active", "disabled", "hovered", "pressed", "inverted"].includes(key);
 }
 function getStyle(
   layer: Layer,

styles/src/styleTree/editor.ts 🔗

@@ -36,8 +36,8 @@ export default function editor(colorScheme: ColorScheme) {
         }),
       },
       message: {
-        text: text(layer, "sans", styleSet, { size: "sm" }),
-        highlightText: text(layer, "sans", styleSet, {
+        text: text(layer, "sans", styleSet, "inverted", { size: "sm" }),
+        highlightText: text(layer, "sans", styleSet, "inverted", {
           size: "sm",
           weight: "bold",
         }),
@@ -153,7 +153,7 @@ export default function editor(colorScheme: ColorScheme) {
       .neutral(0.5)
       .alpha(0.4)
       .hex(), // TODO: This was blend * 2
-    errorColor: foreground(layer, "negative"),
+    errorColor: background(layer, "negative"),
     gutterBackground: background(layer),
     gutterPaddingFactor: 3.5,
     lineNumber: foreground(layer, "disabled"),
@@ -225,7 +225,7 @@ export default function editor(colorScheme: ColorScheme) {
     },
     errorDiagnostic: diagnostic(elevation.middle, "negative"),
     warningDiagnostic: diagnostic(elevation.middle, "warning"),
-    informationDiagnostic: diagnostic(elevation.middle, "info"),
+    informationDiagnostic: diagnostic(elevation.middle, "accent"),
     hintDiagnostic: diagnostic(elevation.middle, "warning"),
     invalidErrorDiagnostic: diagnostic(elevation.middle, "base"),
     invalidHintDiagnostic: diagnostic(elevation.middle, "base"),

styles/src/styleTree/hoverPopover.ts 🔗

@@ -23,8 +23,8 @@ export default function HoverPopover(elevation: Elevation) {
     container: baseContainer,
     infoContainer: {
       ...baseContainer,
-      background: background(layer, "info"),
-      border: border(layer, "info"),
+      background: background(layer, "accent"),
+      border: border(layer, "accent"),
     },
     warningContainer: {
       ...baseContainer,

styles/src/styleTree/picker.ts 🔗

@@ -26,11 +26,11 @@ export default function picker(colorScheme: ColorScheme) {
       },
       cornerRadius: 8,
       text: text(layer, "sans", "variant"),
-      highlightText: text(layer, "sans", "info", { weight: "bold" }),
+      highlightText: text(layer, "sans", "accent", { weight: "bold" }),
       active: {
-        background: background(layer, "active"),
-        text: text(layer, "sans", "active"),
-        highlightText: text(layer, "sans", "info", "active", {
+        background: background(layer, "base", "inverted"),
+        text: text(layer, "sans", "base", "inverted"),
+        highlightText: text(layer, "sans", "accent", "inverted", {
           weight: "bold",
         }),
       },

styles/src/styleTree/statusBar.ts 🔗

@@ -111,7 +111,7 @@ export default function statusBar(colorScheme: ColorScheme) {
         padding: 2,
         margin: { bottom: -1, right: -1 },
         border: border(layer),
-        background: background(layer, "info"),
+        background: background(layer, "accent"),
       },
     },
   };

styles/src/styleTree/tabBar.ts 🔗

@@ -31,7 +31,7 @@ export default function tabBar(colorScheme: ColorScheme) {
 
     // Indicators
     iconConflict: foreground(layer, "warning"),
-    iconDirty: foreground(layer, "info"),
+    iconDirty: foreground(layer, "accent"),
 
     // When two tabs of the same name are open, a label appears next to them
     description: {

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

@@ -49,7 +49,7 @@ export interface Layer {
   base: StyleSet;
   variant: StyleSet;
   on: StyleSet;
-  info: StyleSet;
+  accent: StyleSet;
   positive: StyleSet;
   warning: StyleSet;
   negative: StyleSet;
@@ -74,6 +74,7 @@ export interface StyleSet {
   disabled: Style;
   hovered: Style;
   pressed: Style;
+  inverted: Style;
 }
 
 export interface Style {

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

@@ -12,9 +12,8 @@ import {
 } from "./colorScheme";
 
 export function colorRamp(color: Color): Scale {
-  let hue = color.hsl()[0];
-  let endColor = chroma.hsl(hue, 0.88, 0.96);
-  let startColor = chroma.hsl(hue, 0.68, 0.12);
+  let endColor = color.desaturate(1).brighten(5);
+  let startColor = color.desaturate(1).darken(5);
   return chroma.scale([startColor, color, endColor]).mode("hsl");
 }
 
@@ -58,9 +57,9 @@ export function createColorScheme(
     magenta: baseRamps.magenta,
   };
 
-  let lowest = elevation(resampleSet(baseSet, evenSamples(0, 1)), isLight);
+  let lowest = elevation(resampleSet(baseSet, evenSamples(0, 1)));
 
-  let middle = elevation(resampleSet(baseSet, evenSamples(0.08, 1)), isLight, {
+  let middle = elevation(resampleSet(baseSet, evenSamples(0.08, 1)), {
     blur: 4,
     color: baseSet
       .neutral(isLight ? 7 : 0)
@@ -71,7 +70,7 @@ export function createColorScheme(
   });
   lowest.above = middle;
 
-  let highest = elevation(resampleSet(baseSet, evenSamples(0.16, 1)), isLight, {
+  let highest = elevation(resampleSet(baseSet, evenSamples(0.16, 1)), {
     blur: 16,
     color: baseSet
       .neutral(isLight ? 7 : 0)
@@ -139,35 +138,63 @@ function resample(scale: Scale, samples: number[]): Scale {
 
 function elevation(
   ramps: RampSet,
-  isLight: boolean,
   shadow?: Shadow
 ): Elevation {
   return {
     ramps,
 
-    bottom: bottomLayer(ramps, isLight),
-    middle: middleLayer(ramps, isLight),
-    top: topLayer(ramps, isLight),
+    bottom: bottomLayer(ramps),
+    middle: middleLayer(ramps),
+    top: topLayer(ramps),
 
     shadow,
   };
 }
 
-interface StyleColors {
-  default: number | Color;
-  hovered: number | Color;
-  pressed: number | Color;
-  active: number | Color;
-  disabled: number | Color;
+function bottomLayer(ramps: RampSet): Layer {
+  return {
+    base: buildStyleSet(ramps.neutral, 0.2, 1),
+    variant: buildStyleSet(ramps.neutral, 0.2, 0.7),
+    on: buildStyleSet(ramps.neutral, 0.1, 1),
+    accent: buildStyleSet(ramps.blue, 0.1, 0.5),
+    positive: buildStyleSet(ramps.green, 0.1, 0.5),
+    warning: buildStyleSet(ramps.yellow, 0.1, 0.5),
+    negative: buildStyleSet(ramps.red, 0.1, 0.5),
+  };
+}
+
+function middleLayer(ramps: RampSet): Layer {
+  return {
+    base: buildStyleSet(ramps.neutral, 0.1, 1),
+    variant: buildStyleSet(ramps.neutral, 0.1, 0.7),
+    on: buildStyleSet(ramps.neutral, 0, 1),
+    accent: buildStyleSet(ramps.blue, 0.1, 0.5),
+    positive: buildStyleSet(ramps.green, 0.1, 0.5),
+    warning: buildStyleSet(ramps.yellow, 0.1, 0.5),
+    negative: buildStyleSet(ramps.red, 0.1, 0.5),
+  };
+}
+
+function topLayer(ramps: RampSet): Layer {
+  return {
+    base: buildStyleSet(ramps.neutral, 0, 1),
+    variant: buildStyleSet(ramps.neutral, 0, 0.7),
+    on: buildStyleSet(ramps.neutral, 0.1, 1),
+    accent: buildStyleSet(ramps.blue, 0.1, 0.5),
+    positive: buildStyleSet(ramps.green, 0.1, 0.5),
+    warning: buildStyleSet(ramps.yellow, 0.1, 0.5),
+    negative: buildStyleSet(ramps.red, 0.1, 0.5),
+  };
 }
+
 function buildStyleSet(
   ramp: Scale,
-  styleDefinitions: {
-    background: StyleColors;
-    border: StyleColors;
-    foreground: StyleColors;
-  }
+  backgroundBase: number,
+  foregroundBase: number,
+  step: number = 0.08,
 ): StyleSet {
+  let styleDefinitions = buildStyleDefinition(backgroundBase, foregroundBase, step);
+
   function colorString(indexOrColor: number | Color): string {
     if (typeof indexOrColor === "number") {
       return ramp(indexOrColor).hex();
@@ -190,10 +217,11 @@ function buildStyleSet(
     pressed: buildStyle("pressed"),
     active: buildStyle("active"),
     disabled: buildStyle("disabled"),
+    inverted: buildStyle("inverted"),
   };
 }
 
-function buildLayer(bgBase: number, fgBase: number, step: number) {
+function buildStyleDefinition(bgBase: number, fgBase: number, step: number = 0.08) {
   return {
     background: {
       default: bgBase,
@@ -201,6 +229,7 @@ function buildLayer(bgBase: number, fgBase: number, step: number) {
       pressed: bgBase + step * 1.5,
       active: bgBase + step * 3,
       disabled: bgBase,
+      inverted: fgBase + step * 6,
     },
     border: {
       default: bgBase + step * 1,
@@ -208,49 +237,15 @@ function buildLayer(bgBase: number, fgBase: number, step: number) {
       pressed: bgBase + step,
       active: bgBase + step * 3,
       disabled: bgBase + step * 0.5,
+      inverted: bgBase - step * 3,
     },
     foreground: {
       default: fgBase,
       hovered: fgBase,
       pressed: fgBase,
-      active: fgBase,
+      active: fgBase + step * 6,
       disabled: bgBase + step * 4,
+      inverted: bgBase + step * 2,
     },
   };
-}
-
-function bottomLayer(ramps: RampSet, isLight: boolean): Layer {
-  return {
-    base: buildStyleSet(ramps.neutral, buildLayer(0.2, 1, 0.08)),
-    variant: buildStyleSet(ramps.neutral, buildLayer(0.2, 0.7, 0.08)),
-    on: buildStyleSet(ramps.neutral, buildLayer(0.1, 1, 0.08)),
-    info: buildStyleSet(ramps.blue, buildLayer(0.1, 0.5, 0.08)),
-    positive: buildStyleSet(ramps.green, buildLayer(0.1, 0.5, 0.08)),
-    warning: buildStyleSet(ramps.yellow, buildLayer(0.1, 0.5, 0.08)),
-    negative: buildStyleSet(ramps.red, buildLayer(0.1, 0.5, 0.08)),
-  };
-}
-
-function middleLayer(ramps: RampSet, isLight: boolean): Layer {
-  return {
-    base: buildStyleSet(ramps.neutral, buildLayer(0.1, 1, 0.08)),
-    variant: buildStyleSet(ramps.neutral, buildLayer(0.1, 0.7, 0.08)),
-    on: buildStyleSet(ramps.neutral, buildLayer(0, 1, 0.08)),
-    info: buildStyleSet(ramps.blue, buildLayer(0.1, 0.5, 0.08)),
-    positive: buildStyleSet(ramps.green, buildLayer(0.1, 0.5, 0.08)),
-    warning: buildStyleSet(ramps.yellow, buildLayer(0.1, 0.5, 0.08)),
-    negative: buildStyleSet(ramps.red, buildLayer(0.1, 0.5, 0.08)),
-  };
-}
-
-function topLayer(ramps: RampSet, isLight: boolean): Layer {
-  return {
-    base: buildStyleSet(ramps.neutral, buildLayer(0, 1, 0.08)),
-    variant: buildStyleSet(ramps.neutral, buildLayer(0, 0.7, 0.08)),
-    on: buildStyleSet(ramps.neutral, buildLayer(0.1, 1, 0.08)),
-    info: buildStyleSet(ramps.blue, buildLayer(0.1, 0.5, 0.08)),
-    positive: buildStyleSet(ramps.green, buildLayer(0.1, 0.5, 0.08)),
-    warning: buildStyleSet(ramps.yellow, buildLayer(0.1, 0.5, 0.08)),
-    negative: buildStyleSet(ramps.red, buildLayer(0.1, 0.5, 0.08)),
-  };
-}
+}