Adjust some of the styles to the new Toggleable format

Piotr Osiewicz created

Change summary

crates/collab_ui/src/collab_titlebar_item.rs |   4 
crates/theme/src/theme.rs                    |   8 
crates/workspace/src/toolbar.rs              |   6 
styles/src/styleTree/components.ts           | 436 +++++++-------
styles/src/styleTree/contactList.ts          | 368 ++++++-----
styles/src/styleTree/contactNotification.ts  |  81 +-
styles/src/styleTree/contextMenu.ts          |  91 +-
styles/src/styleTree/copilot.ts              | 491 ++++++++--------
styles/src/styleTree/editor.ts               | 517 ++++++++--------
styles/src/styleTree/picker.ts               | 154 ++--
styles/src/styleTree/projectPanel.ts         | 204 +++---
styles/src/styleTree/statusBar.ts            | 241 ++++---
styles/src/styleTree/tabBar.ts               | 191 +++---
styles/src/styleTree/welcome.ts              | 240 ++++---
styles/src/styleTree/workspace.ts            | 658 +++++++++++----------
15 files changed, 1,907 insertions(+), 1,783 deletions(-)

Detailed changes

crates/collab_ui/src/collab_titlebar_item.rs 🔗

@@ -491,7 +491,7 @@ impl CollabTitlebarItem {
                 .with_child(
                     MouseEventHandler::<ShareUnshare, Self>::new(0, cx, |state, _| {
                         //TODO: Ensure this button has consistent width for both text variations
-                        let style = titlebar.share_button.style_for(state);
+                        let style = titlebar.share_button.inactive_state().style_for(state);
                         Label::new(label, style.text.clone())
                             .contained()
                             .with_style(style.container)
@@ -567,7 +567,7 @@ impl CollabTitlebarItem {
     fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
         let titlebar = &theme.workspace.titlebar;
         MouseEventHandler::<SignIn, Self>::new(0, cx, |state, _| {
-            let style = titlebar.sign_in_prompt.style_for(state);
+            let style = titlebar.sign_in_prompt.inactive_state().style_for(state);
             Label::new("Sign In", style.text.clone())
                 .contained()
                 .with_style(style.container)

crates/theme/src/theme.rs 🔗

@@ -128,12 +128,12 @@ pub struct Titlebar {
     pub leader_avatar: AvatarStyle,
     pub follower_avatar: AvatarStyle,
     pub inactive_avatar_grayscale: bool,
-    pub sign_in_prompt: Interactive<ContainedText>,
+    pub sign_in_prompt: Toggleable<Interactive<ContainedText>>,
     pub outdated_warning: ContainedText,
-    pub share_button: Interactive<ContainedText>,
+    pub share_button: Toggleable<Interactive<ContainedText>>,
     pub call_control: Interactive<IconButton>,
     pub toggle_contacts_button: Toggleable<Interactive<IconButton>>,
-    pub user_menu_button: Interactive<IconButton>,
+    pub user_menu_button: Toggleable<Interactive<IconButton>>,
     pub toggle_contacts_badge: ContainerStyle,
 }
 
@@ -339,7 +339,7 @@ pub struct Toolbar {
     pub container: ContainerStyle,
     pub height: f32,
     pub item_spacing: f32,
-    pub nav_button: Toggleable<Interactive<IconButton>>,
+    pub nav_button: Interactive<IconButton>,
 }
 
 #[derive(Clone, Deserialize, Default)]

crates/workspace/src/toolbar.rs 🔗

@@ -219,7 +219,7 @@ impl View for Toolbar {
 #[allow(clippy::too_many_arguments)]
 fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>)>(
     svg_path: &'static str,
-    style: theme::Toggleable<theme::Interactive<theme::IconButton>>,
+    style: theme::Interactive<theme::IconButton>,
     nav_button_height: f32,
     tooltip_style: TooltipStyle,
     enabled: bool,
@@ -231,9 +231,9 @@ fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>
 ) -> AnyElement<Toolbar> {
     MouseEventHandler::<A, _>::new(0, cx, |state, _| {
         let style = if enabled {
-            style.inactive_state().style_for(state)
+            style.style_for(state)
         } else {
-            style.inactive_state().disabled_style()
+            style.disabled_style()
         };
         Svg::new(svg_path)
             .with_color(style.color)

styles/src/styleTree/components.ts 🔗

@@ -2,297 +2,297 @@ import { fontFamilies, fontSizes, FontWeight } from "../common"
 import { Layer, Styles, StyleSets, Style } from "../theme/colorScheme"
 
 function isStyleSet(key: any): key is StyleSets {
-    return [
-        "base",
-        "variant",
-        "on",
-        "accent",
-        "positive",
-        "warning",
-        "negative",
-    ].includes(key)
+  return [
+    "base",
+    "variant",
+    "on",
+    "accent",
+    "positive",
+    "warning",
+    "negative",
+  ].includes(key)
 }
 
 function isStyle(key: any): key is Styles {
-    return [
-        "default",
-        "active",
-        "disabled",
-        "hovered",
-        "pressed",
-        "inverted",
-    ].includes(key)
+  return [
+    "default",
+    "active",
+    "disabled",
+    "hovered",
+    "pressed",
+    "inverted",
+  ].includes(key)
 }
 function getStyle(
-    layer: Layer,
-    possibleStyleSetOrStyle?: any,
-    possibleStyle?: any
+  layer: Layer,
+  possibleStyleSetOrStyle?: any,
+  possibleStyle?: any
 ): Style {
-    let styleSet: StyleSets = "base"
-    let style: Styles = "default"
-    if (isStyleSet(possibleStyleSetOrStyle)) {
-        styleSet = possibleStyleSetOrStyle
-    } else if (isStyle(possibleStyleSetOrStyle)) {
-        style = possibleStyleSetOrStyle
-    }
+  let styleSet: StyleSets = "base"
+  let style: Styles = "default"
+  if (isStyleSet(possibleStyleSetOrStyle)) {
+    styleSet = possibleStyleSetOrStyle
+  } else if (isStyle(possibleStyleSetOrStyle)) {
+    style = possibleStyleSetOrStyle
+  }
 
-    if (isStyle(possibleStyle)) {
-        style = possibleStyle
-    }
+  if (isStyle(possibleStyle)) {
+    style = possibleStyle
+  }
 
-    return layer[styleSet][style]
+  return layer[styleSet][style]
 }
 
 export function background(layer: Layer, style?: Styles): string
 export function background(
-    layer: Layer,
-    styleSet?: StyleSets,
-    style?: Styles
+  layer: Layer,
+  styleSet?: StyleSets,
+  style?: Styles
 ): string
 export function background(
-    layer: Layer,
-    styleSetOrStyles?: StyleSets | Styles,
-    style?: Styles
+  layer: Layer,
+  styleSetOrStyles?: StyleSets | Styles,
+  style?: Styles
 ): string {
-    return getStyle(layer, styleSetOrStyles, style).background
+  return getStyle(layer, styleSetOrStyles, style).background
 }
 
 export function borderColor(layer: Layer, style?: Styles): string
 export function borderColor(
-    layer: Layer,
-    styleSet?: StyleSets,
-    style?: Styles
+  layer: Layer,
+  styleSet?: StyleSets,
+  style?: Styles
 ): string
 export function borderColor(
-    layer: Layer,
-    styleSetOrStyles?: StyleSets | Styles,
-    style?: Styles
+  layer: Layer,
+  styleSetOrStyles?: StyleSets | Styles,
+  style?: Styles
 ): string {
-    return getStyle(layer, styleSetOrStyles, style).border
+  return getStyle(layer, styleSetOrStyles, style).border
 }
 
 export function foreground(layer: Layer, style?: Styles): string
 export function foreground(
-    layer: Layer,
-    styleSet?: StyleSets,
-    style?: Styles
+  layer: Layer,
+  styleSet?: StyleSets,
+  style?: Styles
 ): string
 export function foreground(
-    layer: Layer,
-    styleSetOrStyles?: StyleSets | Styles,
-    style?: Styles
+  layer: Layer,
+  styleSetOrStyles?: StyleSets | Styles,
+  style?: Styles
 ): string {
-    return getStyle(layer, styleSetOrStyles, style).foreground
+  return getStyle(layer, styleSetOrStyles, style).foreground
 }
 
-interface Text {
-    family: keyof typeof fontFamilies
-    color: string
-    size: number
-    weight?: FontWeight
-    underline?: boolean
+interface Text extends Object {
+  family: keyof typeof fontFamilies
+  color: string
+  size: number
+  weight?: FontWeight
+  underline?: boolean
 }
 
 export interface TextProperties {
-    size?: keyof typeof fontSizes
-    weight?: FontWeight
-    underline?: boolean
-    color?: string
-    features?: FontFeatures
+  size?: keyof typeof fontSizes
+  weight?: FontWeight
+  underline?: boolean
+  color?: string
+  features?: FontFeatures
 }
 
 interface FontFeatures {
-    /** Contextual Alternates: Applies a second substitution feature based on a match of a character pattern within a context of surrounding patterns */
-    calt?: boolean
-    /** Case-Sensitive Forms: Shifts various punctuation marks up to a position that works better with all-capital sequences */
-    case?: boolean
-    /** Capital Spacing: Adjusts inter-glyph spacing for all-capital text */
-    cpsp?: boolean
-    /** Fractions: Replaces figures separated by a slash with diagonal fractions */
-    frac?: boolean
-    /** Standard Ligatures: Replaces a sequence of glyphs with a single glyph which is preferred for typographic purposes */
-    liga?: boolean
-    /** Oldstyle Figures: Changes selected figures from the default or lining style to oldstyle form. */
-    onum?: boolean
-    /** Ordinals: Replaces default alphabetic glyphs with the corresponding ordinal forms for use after figures */
-    ordn?: boolean
-    /** Proportional Figures: Replaces figure glyphs set on uniform (tabular) widths with corresponding glyphs set on proportional widths */
-    pnum?: boolean
-    /** Stylistic set 01 */
-    ss01?: boolean
-    /** Stylistic set 02 */
-    ss02?: boolean
-    /** Stylistic set 03 */
-    ss03?: boolean
-    /** Stylistic set 04 */
-    ss04?: boolean
-    /** Stylistic set 05 */
-    ss05?: boolean
-    /** Stylistic set 06 */
-    ss06?: boolean
-    /** Stylistic set 07 */
-    ss07?: boolean
-    /** Stylistic set 08 */
-    ss08?: boolean
-    /** Stylistic set 09 */
-    ss09?: boolean
-    /** Stylistic set 10 */
-    ss10?: boolean
-    /** Stylistic set 11 */
-    ss11?: boolean
-    /** Stylistic set 12 */
-    ss12?: boolean
-    /** Stylistic set 13 */
-    ss13?: boolean
-    /** Stylistic set 14 */
-    ss14?: boolean
-    /** Stylistic set 15 */
-    ss15?: boolean
-    /** Stylistic set 16 */
-    ss16?: boolean
-    /** Stylistic set 17 */
-    ss17?: boolean
-    /** Stylistic set 18 */
-    ss18?: boolean
-    /** Stylistic set 19 */
-    ss19?: boolean
-    /** Stylistic set 20 */
-    ss20?: boolean
-    /** Subscript: Replaces default glyphs with subscript glyphs */
-    subs?: boolean
-    /** Superscript: Replaces default glyphs with superscript glyphs */
-    sups?: boolean
-    /** Swash: Replaces default glyphs with swash glyphs for stylistic purposes */
-    swsh?: boolean
-    /** Titling: Replaces default glyphs with titling glyphs for use in large-size settings */
-    titl?: boolean
-    /** Tabular Figures: Replaces figure glyphs set on proportional widths with corresponding glyphs set on uniform (tabular) widths */
-    tnum?: boolean
-    /** Slashed Zero: Replaces default zero with a slashed zero for better distinction between "0" and "O" */
-    zero?: boolean
+  /** Contextual Alternates: Applies a second substitution feature based on a match of a character pattern within a context of surrounding patterns */
+  calt?: boolean
+  /** Case-Sensitive Forms: Shifts various punctuation marks up to a position that works better with all-capital sequences */
+  case?: boolean
+  /** Capital Spacing: Adjusts inter-glyph spacing for all-capital text */
+  cpsp?: boolean
+  /** Fractions: Replaces figures separated by a slash with diagonal fractions */
+  frac?: boolean
+  /** Standard Ligatures: Replaces a sequence of glyphs with a single glyph which is preferred for typographic purposes */
+  liga?: boolean
+  /** Oldstyle Figures: Changes selected figures from the default or lining style to oldstyle form. */
+  onum?: boolean
+  /** Ordinals: Replaces default alphabetic glyphs with the corresponding ordinal forms for use after figures */
+  ordn?: boolean
+  /** Proportional Figures: Replaces figure glyphs set on uniform (tabular) widths with corresponding glyphs set on proportional widths */
+  pnum?: boolean
+  /** Stylistic set 01 */
+  ss01?: boolean
+  /** Stylistic set 02 */
+  ss02?: boolean
+  /** Stylistic set 03 */
+  ss03?: boolean
+  /** Stylistic set 04 */
+  ss04?: boolean
+  /** Stylistic set 05 */
+  ss05?: boolean
+  /** Stylistic set 06 */
+  ss06?: boolean
+  /** Stylistic set 07 */
+  ss07?: boolean
+  /** Stylistic set 08 */
+  ss08?: boolean
+  /** Stylistic set 09 */
+  ss09?: boolean
+  /** Stylistic set 10 */
+  ss10?: boolean
+  /** Stylistic set 11 */
+  ss11?: boolean
+  /** Stylistic set 12 */
+  ss12?: boolean
+  /** Stylistic set 13 */
+  ss13?: boolean
+  /** Stylistic set 14 */
+  ss14?: boolean
+  /** Stylistic set 15 */
+  ss15?: boolean
+  /** Stylistic set 16 */
+  ss16?: boolean
+  /** Stylistic set 17 */
+  ss17?: boolean
+  /** Stylistic set 18 */
+  ss18?: boolean
+  /** Stylistic set 19 */
+  ss19?: boolean
+  /** Stylistic set 20 */
+  ss20?: boolean
+  /** Subscript: Replaces default glyphs with subscript glyphs */
+  subs?: boolean
+  /** Superscript: Replaces default glyphs with superscript glyphs */
+  sups?: boolean
+  /** Swash: Replaces default glyphs with swash glyphs for stylistic purposes */
+  swsh?: boolean
+  /** Titling: Replaces default glyphs with titling glyphs for use in large-size settings */
+  titl?: boolean
+  /** Tabular Figures: Replaces figure glyphs set on proportional widths with corresponding glyphs set on uniform (tabular) widths */
+  tnum?: boolean
+  /** Slashed Zero: Replaces default zero with a slashed zero for better distinction between "0" and "O" */
+  zero?: boolean
 }
 
 export function text(
-    layer: Layer,
-    fontFamily: keyof typeof fontFamilies,
-    styleSet: StyleSets,
-    style: Styles,
-    properties?: TextProperties
+  layer: Layer,
+  fontFamily: keyof typeof fontFamilies,
+  styleSet: StyleSets,
+  style: Styles,
+  properties?: TextProperties
 ): Text
 export function text(
-    layer: Layer,
-    fontFamily: keyof typeof fontFamilies,
-    styleSet: StyleSets,
-    properties?: TextProperties
+  layer: Layer,
+  fontFamily: keyof typeof fontFamilies,
+  styleSet: StyleSets,
+  properties?: TextProperties
 ): Text
 export function text(
-    layer: Layer,
-    fontFamily: keyof typeof fontFamilies,
-    style: Styles,
-    properties?: TextProperties
+  layer: Layer,
+  fontFamily: keyof typeof fontFamilies,
+  style: Styles,
+  properties?: TextProperties
 ): Text
 export function text(
-    layer: Layer,
-    fontFamily: keyof typeof fontFamilies,
-    properties?: TextProperties
+  layer: Layer,
+  fontFamily: keyof typeof fontFamilies,
+  properties?: TextProperties
 ): Text
 export function text(
-    layer: Layer,
-    fontFamily: keyof typeof fontFamilies,
-    styleSetStyleOrProperties?: StyleSets | Styles | TextProperties,
-    styleOrProperties?: Styles | TextProperties,
-    properties?: TextProperties
+  layer: Layer,
+  fontFamily: keyof typeof fontFamilies,
+  styleSetStyleOrProperties?: StyleSets | Styles | TextProperties,
+  styleOrProperties?: Styles | TextProperties,
+  properties?: TextProperties
 ) {
-    let style = getStyle(layer, styleSetStyleOrProperties, styleOrProperties)
+  let style = getStyle(layer, styleSetStyleOrProperties, styleOrProperties)
 
-    if (typeof styleSetStyleOrProperties === "object") {
-        properties = styleSetStyleOrProperties
-    }
-    if (typeof styleOrProperties === "object") {
-        properties = styleOrProperties
-    }
+  if (typeof styleSetStyleOrProperties === "object") {
+    properties = styleSetStyleOrProperties
+  }
+  if (typeof styleOrProperties === "object") {
+    properties = styleOrProperties
+  }
 
-    let size = fontSizes[properties?.size || "sm"]
-    let color = properties?.color || style.foreground
+  let size = fontSizes[properties?.size || "sm"]
+  let color = properties?.color || style.foreground
 
-    return {
-        family: fontFamilies[fontFamily],
-        ...properties,
-        color,
-        size,
-    }
+  return {
+    family: fontFamilies[fontFamily],
+    ...properties,
+    color,
+    size,
+  }
 }
 
 export interface Border {
-    color: string
-    width: number
-    top?: boolean
-    bottom?: boolean
-    left?: boolean
-    right?: boolean
-    overlay?: boolean
+  color: string
+  width: number
+  top?: boolean
+  bottom?: boolean
+  left?: boolean
+  right?: boolean
+  overlay?: boolean
 }
 
 export interface BorderProperties {
-    width?: number
-    top?: boolean
-    bottom?: boolean
-    left?: boolean
-    right?: boolean
-    overlay?: boolean
+  width?: number
+  top?: boolean
+  bottom?: boolean
+  left?: boolean
+  right?: boolean
+  overlay?: boolean
 }
 
 export function border(
-    layer: Layer,
-    styleSet: StyleSets,
-    style: Styles,
-    properties?: BorderProperties
+  layer: Layer,
+  styleSet: StyleSets,
+  style: Styles,
+  properties?: BorderProperties
 ): Border
 export function border(
-    layer: Layer,
-    styleSet: StyleSets,
-    properties?: BorderProperties
+  layer: Layer,
+  styleSet: StyleSets,
+  properties?: BorderProperties
 ): Border
 export function border(
-    layer: Layer,
-    style: Styles,
-    properties?: BorderProperties
+  layer: Layer,
+  style: Styles,
+  properties?: BorderProperties
 ): Border
 export function border(layer: Layer, properties?: BorderProperties): Border
 export function border(
-    layer: Layer,
-    styleSetStyleOrProperties?: StyleSets | Styles | BorderProperties,
-    styleOrProperties?: Styles | BorderProperties,
-    properties?: BorderProperties
+  layer: Layer,
+  styleSetStyleOrProperties?: StyleSets | Styles | BorderProperties,
+  styleOrProperties?: Styles | BorderProperties,
+  properties?: BorderProperties
 ): Border {
-    let style = getStyle(layer, styleSetStyleOrProperties, styleOrProperties)
+  let style = getStyle(layer, styleSetStyleOrProperties, styleOrProperties)
 
-    if (typeof styleSetStyleOrProperties === "object") {
-        properties = styleSetStyleOrProperties
-    }
-    if (typeof styleOrProperties === "object") {
-        properties = styleOrProperties
-    }
+  if (typeof styleSetStyleOrProperties === "object") {
+    properties = styleSetStyleOrProperties
+  }
+  if (typeof styleOrProperties === "object") {
+    properties = styleOrProperties
+  }
 
-    return {
-        color: style.border,
-        width: 1,
-        ...properties,
-    }
+  return {
+    color: style.border,
+    width: 1,
+    ...properties,
+  }
 }
 
 export function svg(
-    color: string,
-    asset: String,
-    width: Number,
-    height: Number
+  color: string,
+  asset: String,
+  width: Number,
+  height: Number
 ) {
-    return {
-        color,
-        asset,
-        dimensions: {
-            width,
-            height,
-        },
-    }
+  return {
+    color,
+    asset,
+    dimensions: {
+      width,
+      height,
+    },
+  }
 }

styles/src/styleTree/contactList.ts 🔗

@@ -1,182 +1,206 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, borderColor, foreground, text } from "./components"
-
+import { toggleable } from "./toggle"
+import { interactive } from "./interactive"
 export default function contactsPanel(colorScheme: ColorScheme) {
-    const nameMargin = 8
-    const sidePadding = 12
+  const nameMargin = 8
+  const sidePadding = 12
 
-    let layer = colorScheme.middle
+  let layer = colorScheme.middle
 
-    const contactButton = {
-        background: background(layer, "on"),
-        color: foreground(layer, "on"),
-        iconWidth: 8,
-        buttonWidth: 16,
-        cornerRadius: 8,
-    }
-    const projectRow = {
-        guestAvatarSpacing: 4,
-        height: 24,
-        guestAvatar: {
-            cornerRadius: 8,
-            width: 14,
-        },
-        name: {
-            ...text(layer, "mono", { size: "sm" }),
-            margin: {
-                left: nameMargin,
-                right: 6,
-            },
-        },
-        guests: {
-            margin: {
-                left: nameMargin,
-                right: nameMargin,
-            },
-        },
-        padding: {
+  const contactButton = {
+    background: background(layer, "on"),
+    color: foreground(layer, "on"),
+    iconWidth: 8,
+    buttonWidth: 16,
+    cornerRadius: 8,
+  }
+  const projectRow = {
+    guestAvatarSpacing: 4,
+    height: 24,
+    guestAvatar: {
+      cornerRadius: 8,
+      width: 14,
+    },
+    name: {
+      ...text(layer, "mono", { size: "sm" }),
+      margin: {
+        left: nameMargin,
+        right: 6,
+      },
+    },
+    guests: {
+      margin: {
+        left: nameMargin,
+        right: nameMargin,
+      },
+    },
+    padding: {
+      left: sidePadding,
+      right: sidePadding,
+    },
+  }
+
+  return {
+    background: background(layer),
+    padding: { top: 12 },
+    userQueryEditor: {
+      background: background(layer, "on"),
+      cornerRadius: 6,
+      text: text(layer, "mono", "on"),
+      placeholderText: text(layer, "mono", "on", "disabled", {
+        size: "xs",
+      }),
+      selection: colorScheme.players[0],
+      border: border(layer, "on"),
+      padding: {
+        bottom: 4,
+        left: 8,
+        right: 8,
+        top: 4,
+      },
+      margin: {
+        left: 6,
+      },
+    },
+    userQueryEditorHeight: 33,
+    addContactButton: {
+      margin: { left: 6, right: 12 },
+      color: foreground(layer, "on"),
+      buttonWidth: 28,
+      iconWidth: 16,
+    },
+    rowHeight: 28,
+    sectionIconSize: 8,
+    headerRow: toggleable(interactive({
+      ...text(layer, "mono", { size: "sm" }),
+      margin: { top: 14 },
+      padding: {
+        left: sidePadding,
+        right: sidePadding,
+      },
+      background: background(layer, "default"),// posiewic: breaking change
+    }, {}),
+      {
+        default: {
+          ...text(layer, "mono", "active", { size: "sm" }),
+          background: background(layer, "active"),
+        },
+      }),
+    leaveCall: interactive({
+      background: background(layer),
+      border: border(layer),
+      cornerRadius: 6,
+      margin: {
+        top: 1,
+      },
+      padding: {
+        top: 1,
+        bottom: 1,
+        left: 7,
+        right: 7,
+      },
+      ...text(layer, "sans", "variant", { size: "xs" }),
+    },
+      {
+        hover: {
+          ...text(layer, "sans", "hovered", { size: "xs" }),
+          background: background(layer, "hovered"),
+          border: border(layer, "hovered"),
+        }
+      }
+    ),
+    contactRow: {
+      inactive: {
+        default: {
+          padding: {
             left: sidePadding,
             right: sidePadding,
+          }
         },
-    }
+      },
+      active: {
+        default: {
+          background: background(layer, "active"),
+          padding: {
+            left: sidePadding,
+            right: sidePadding,
+          }
+        }
+      },
+    },
 
-    return {
-        background: background(layer),
-        padding: { top: 12 },
-        userQueryEditor: {
-            background: background(layer, "on"),
-            cornerRadius: 6,
-            text: text(layer, "mono", "on"),
-            placeholderText: text(layer, "mono", "on", "disabled", {
-                size: "xs",
-            }),
-            selection: colorScheme.players[0],
-            border: border(layer, "on"),
-            padding: {
-                bottom: 4,
-                left: 8,
-                right: 8,
-                top: 4,
-            },
-            margin: {
-                left: 6,
-            },
-        },
-        userQueryEditorHeight: 33,
-        addContactButton: {
-            margin: { left: 6, right: 12 },
-            color: foreground(layer, "on"),
-            buttonWidth: 28,
-            iconWidth: 16,
-        },
-        rowHeight: 28,
-        sectionIconSize: 8,
-        headerRow: {
-            ...text(layer, "mono", { size: "sm" }),
-            margin: { top: 14 },
-            padding: {
-                left: sidePadding,
-                right: sidePadding,
-            },
-            active: {
-                ...text(layer, "mono", "active", { size: "sm" }),
-                background: background(layer, "active"),
-            },
-        },
-        leaveCall: {
-            background: background(layer),
-            border: border(layer),
-            cornerRadius: 6,
-            margin: {
-                top: 1,
-            },
-            padding: {
-                top: 1,
-                bottom: 1,
-                left: 7,
-                right: 7,
-            },
-            ...text(layer, "sans", "variant", { size: "xs" }),
-            hover: {
-                ...text(layer, "sans", "hovered", { size: "xs" }),
-                background: background(layer, "hovered"),
-                border: border(layer, "hovered"),
-            },
-        },
-        contactRow: {
-            padding: {
-                left: sidePadding,
-                right: sidePadding,
-            },
-            active: {
-                background: background(layer, "active"),
-            },
-        },
-        contactAvatar: {
-            cornerRadius: 10,
-            width: 18,
-        },
-        contactStatusFree: {
-            cornerRadius: 4,
-            padding: 4,
-            margin: { top: 12, left: 12 },
-            background: foreground(layer, "positive"),
-        },
-        contactStatusBusy: {
-            cornerRadius: 4,
-            padding: 4,
-            margin: { top: 12, left: 12 },
-            background: foreground(layer, "negative"),
-        },
-        contactUsername: {
-            ...text(layer, "mono", { size: "sm" }),
-            margin: {
-                left: nameMargin,
-            },
-        },
-        contactButtonSpacing: nameMargin,
-        contactButton: {
-            ...contactButton,
-            hover: {
-                background: background(layer, "hovered"),
-            },
-        },
-        disabledButton: {
-            ...contactButton,
-            background: background(layer, "on"),
-            color: foreground(layer, "on"),
-        },
-        callingIndicator: {
-            ...text(layer, "mono", "variant", { size: "xs" }),
-        },
-        treeBranch: {
-            color: borderColor(layer),
-            width: 1,
-            hover: {
-                color: borderColor(layer),
-            },
-            active: {
-                color: borderColor(layer),
-            },
-        },
-        projectRow: {
-            ...projectRow,
-            background: background(layer),
-            icon: {
-                margin: { left: nameMargin },
-                color: foreground(layer, "variant"),
-                width: 12,
-            },
-            name: {
-                ...projectRow.name,
-                ...text(layer, "mono", { size: "sm" }),
-            },
-            hover: {
-                background: background(layer, "hovered"),
-            },
-            active: {
-                background: background(layer, "active"),
-            },
-        },
-    }
+    contactAvatar: {
+      cornerRadius: 10,
+      width: 18,
+    },
+    contactStatusFree: {
+      cornerRadius: 4,
+      padding: 4,
+      margin: { top: 12, left: 12 },
+      background: foreground(layer, "positive"),
+    },
+    contactStatusBusy: {
+      cornerRadius: 4,
+      padding: 4,
+      margin: { top: 12, left: 12 },
+      background: foreground(layer, "negative"),
+    },
+    contactUsername: {
+      ...text(layer, "mono", { size: "sm" }),
+      margin: {
+        left: nameMargin,
+      },
+    },
+    contactButtonSpacing: nameMargin,
+    contactButton: interactive(
+      contactButton,
+      {
+        hover: {
+          background: background(layer, "hovered"),
+        },
+      }),
+    disabledButton: {
+      ...contactButton,
+      background: background(layer, "on"),
+      color: foreground(layer, "on"),
+    },
+    callingIndicator: {
+      ...text(layer, "mono", "variant", { size: "xs" }),
+    },
+    treeBranch: toggleable(interactive({
+      color: borderColor(layer),
+      width: 1,
+    },
+      {
+        hover: {
+          color: borderColor(layer),
+        },
+      }),
+      {
+        default: {
+          color: borderColor(layer),
+        },
+      }
+    ),
+    projectRow: {
+      ...projectRow,
+      background: background(layer),
+      icon: {
+        margin: { left: nameMargin },
+        color: foreground(layer, "variant"),
+        width: 12,
+      },
+      name: {
+        ...projectRow.name,
+        ...text(layer, "mono", { size: "sm" }),
+      },
+      hover: {
+        background: background(layer, "hovered"),
+      },
+      active: {
+        background: background(layer, "active"),
+      },
+    },
+  }
 }

styles/src/styleTree/contactNotification.ts 🔗

@@ -1,45 +1,52 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, foreground, text } from "./components"
-
+import { interactive } from "./interactive"
 const avatarSize = 12
 const headerPadding = 8
 
 export default function contactNotification(colorScheme: ColorScheme): Object {
-    let layer = colorScheme.lowest
-    return {
-        headerAvatar: {
-            height: avatarSize,
-            width: avatarSize,
-            cornerRadius: 6,
-        },
-        headerMessage: {
-            ...text(layer, "sans", { size: "xs" }),
-            margin: { left: headerPadding, right: headerPadding },
-        },
-        headerHeight: 18,
-        bodyMessage: {
-            ...text(layer, "sans", { size: "xs" }),
-            margin: { left: avatarSize + headerPadding, top: 6, bottom: 6 },
-        },
-        button: {
-            ...text(layer, "sans", "on", { size: "xs" }),
-            background: background(layer, "on"),
-            padding: 4,
-            cornerRadius: 6,
-            margin: { left: 6 },
-            hover: {
-                background: background(layer, "on", "hovered"),
-            },
-        },
-        dismissButton: {
-            color: foreground(layer, "variant"),
-            iconWidth: 8,
-            iconHeight: 8,
-            buttonWidth: 8,
-            buttonHeight: 8,
-            hover: {
-                color: foreground(layer, "hovered"),
-            },
+  let layer = colorScheme.lowest
+  return {
+    headerAvatar: {
+      height: avatarSize,
+      width: avatarSize,
+      cornerRadius: 6,
+    },
+    headerMessage: {
+      ...text(layer, "sans", { size: "xs" }),
+      margin: { left: headerPadding, right: headerPadding },
+    },
+    headerHeight: 18,
+    bodyMessage: {
+      ...text(layer, "sans", { size: "xs" }),
+      margin: { left: avatarSize + headerPadding, top: 6, bottom: 6 },
+    },
+    button:
+      interactive({
+        ...text(layer, "sans", "on", { size: "xs" }),
+        background: background(layer, "on"),
+        padding: 4,
+        cornerRadius: 6,
+        margin: { left: 6 }
+      },
+
+        {
+          hover: {
+            background: background(layer, "on", "hovered"),
+          }
+        }),
+
+    dismissButton: {
+      default: {
+        color: foreground(layer, "variant"),
+        iconWidth: 8,
+        iconHeight: 8,
+        buttonWidth: 8,
+        buttonHeight: 8,
+        hover: {
+          color: foreground(layer, "hovered"),
         },
-    }
+      }
+    },
+  }
 }

styles/src/styleTree/contextMenu.ts 🔗

@@ -1,49 +1,54 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, borderColor, text } from "./components"
+import { interactive } from "./interactive"
+import { toggleable } from "./toggle"
 
 export default function contextMenu(colorScheme: ColorScheme) {
-    let layer = colorScheme.middle
-    return {
-        background: background(layer),
-        cornerRadius: 10,
-        padding: 4,
-        shadow: colorScheme.popoverShadow,
-        border: border(layer),
-        keystrokeMargin: 30,
-        item: {
-            iconSpacing: 8,
-            iconWidth: 14,
-            padding: { left: 6, right: 6, top: 2, bottom: 2 },
-            cornerRadius: 6,
-            label: text(layer, "sans", { size: "sm" }),
-            keystroke: {
-                ...text(layer, "sans", "variant", {
-                    size: "sm",
-                    weight: "bold",
-                }),
-                padding: { left: 3, right: 3 },
-            },
-            hover: {
-                background: background(layer, "hovered"),
-                label: text(layer, "sans", "hovered", { size: "sm" }),
-                keystroke: {
-                    ...text(layer, "sans", "hovered", {
-                        size: "sm",
-                        weight: "bold",
-                    }),
-                    padding: { left: 3, right: 3 },
-                },
-            },
-            active: {
-                background: background(layer, "active"),
-            },
-            activeHover: {
-                background: background(layer, "active"),
-            },
+  let layer = colorScheme.middle
+  return {
+    background: background(layer),
+    cornerRadius: 10,
+    padding: 4,
+    shadow: colorScheme.popoverShadow,
+    border: border(layer),
+    keystrokeMargin: 30,
+    item: toggleable(interactive({
+      iconSpacing: 8,
+      iconWidth: 14,
+      padding: { left: 6, right: 6, top: 2, bottom: 2 },
+      cornerRadius: 6,
+      label: text(layer, "sans", { size: "sm" }),
+      keystroke: {
+        ...text(layer, "sans", "variant", {
+          size: "sm",
+          weight: "bold",
+        }),
+        padding: { left: 3, right: 3 },
+      }
+    }, {
+      hover: {
+        background: background(layer, "hovered"),
+        label: text(layer, "sans", "hovered", { size: "sm" }),
+        keystroke: {
+          ...text(layer, "sans", "hovered", {
+            size: "sm",
+            weight: "bold",
+          }),
+          padding: { left: 3, right: 3 },
         },
-        separator: {
-            background: borderColor(layer),
-            margin: { top: 2, bottom: 2 },
-        },
-    }
+      }
+    }), {
+      default: {
+        background: background(layer, "active"),
+      },
+      hover: {
+        background: background(layer, "active"),
+      },
+    }),
+
+    separator: {
+      background: borderColor(layer),
+      margin: { top: 2, bottom: 2 },
+    },
+  }
 }

styles/src/styleTree/copilot.ts 🔗

@@ -1,267 +1,278 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, foreground, svg, text } from "./components"
-
+import { interactive } from "./interactive"
 export default function copilot(colorScheme: ColorScheme) {
-    let layer = colorScheme.middle
+  let layer = colorScheme.middle
 
-    let content_width = 264
+  let content_width = 264
 
-    let ctaButton = {
-        // Copied from welcome screen. FIXME: Move this into a ZDS component
-        background: background(layer),
-        border: border(layer, "default"),
-        cornerRadius: 4,
-        margin: {
-            top: 4,
-            bottom: 4,
-            left: 8,
-            right: 8,
-        },
-        padding: {
-            top: 3,
-            bottom: 3,
-            left: 7,
-            right: 7,
-        },
-        ...text(layer, "sans", "default", { size: "sm" }),
+  let ctaButton =
+    // Copied from welcome screen. FIXME: Move this into a ZDS component
+    interactive({
+      background: background(layer),
+      border: border(layer, "default"),
+      cornerRadius: 4,
+      margin: {
+        top: 4,
+        bottom: 4,
+        left: 8,
+        right: 8,
+      },
+      padding: {
+        top: 3,
+        bottom: 3,
+        left: 7,
+        right: 7,
+      },
+      ...text(layer, "sans", "default", { size: "sm" })
+    },
+      {
         hover: {
-            ...text(layer, "sans", "default", { size: "sm" }),
-            background: background(layer, "hovered"),
-            border: border(layer, "active"),
+          ...text(layer, "sans", "default", { size: "sm" }),
+          background: background(layer, "hovered"),
+          border: border(layer, "active"),
         },
-    }
+      });
 
-    return {
-        outLinkIcon: {
-            icon: svg(
-                foreground(layer, "variant"),
-                "icons/link_out_12.svg",
-                12,
-                12
-            ),
-            container: {
-                cornerRadius: 6,
-                padding: { left: 6 },
-            },
-            hover: {
-                icon: svg(
-                    foreground(layer, "hovered"),
-                    "icons/link_out_12.svg",
-                    12,
-                    12
-                ),
-            },
+  return {
+    outLinkIcon:
+      interactive({
+        icon: svg(
+          foreground(layer, "variant"),
+          "icons/link_out_12.svg",
+          12,
+          12
+        ),
+        container: {
+          cornerRadius: 6,
+          padding: { left: 6 },
         },
-        modal: {
-            titleText: {
-                ...text(layer, "sans", { size: "xs", weight: "bold" }),
-            },
-            titlebar: {
-                background: background(colorScheme.lowest),
-                border: border(layer, "active"),
-                padding: {
-                    top: 4,
-                    bottom: 4,
-                    left: 8,
-                    right: 8,
-                },
-            },
-            container: {
-                background: background(colorScheme.lowest),
-                padding: {
-                    top: 0,
-                    left: 0,
-                    right: 0,
-                    bottom: 8,
-                },
-            },
-            closeIcon: {
-                icon: svg(
-                    foreground(layer, "variant"),
-                    "icons/x_mark_8.svg",
-                    8,
-                    8
-                ),
-                container: {
-                    cornerRadius: 2,
-                    padding: {
-                        top: 4,
-                        bottom: 4,
-                        left: 4,
-                        right: 4,
-                    },
-                    margin: {
-                        right: 0,
-                    },
-                },
-                hover: {
-                    icon: svg(
-                        foreground(layer, "on"),
-                        "icons/x_mark_8.svg",
-                        8,
-                        8
-                    ),
-                },
-                clicked: {
-                    icon: svg(
-                        foreground(layer, "base"),
-                        "icons/x_mark_8.svg",
-                        8,
-                        8
-                    ),
-                },
+      },
+        {
+          hover: {
+            icon: {
+              color:
+                foreground(layer, "hovered")
+            }
+          },
+        }),
+
+    modal: {
+      titleText: {
+        default: {
+          ...text(layer, "sans", { size: "xs", weight: "bold" })
+        }
+      },
+      titlebar: {
+        background: background(colorScheme.lowest),
+        border: border(layer, "active"),
+        padding: {
+          top: 4,
+          bottom: 4,
+          left: 8,
+          right: 8,
+        },
+      },
+      container: {
+        background: background(colorScheme.lowest),
+        padding: {
+          top: 0,
+          left: 0,
+          right: 0,
+          bottom: 8,
+        },
+      },
+      closeIcon: interactive(
+        {
+          icon: svg(
+            foreground(layer, "variant"),
+            "icons/x_mark_8.svg",
+            8,
+            8
+          ),
+          container: {
+            cornerRadius: 2,
+            padding: {
+              top: 4,
+              bottom: 4,
+              left: 4,
+              right: 4,
             },
-            dimensions: {
-                width: 280,
-                height: 280,
+            margin: {
+              right: 0,
             },
+          }
         },
+        {
+          hover: {
+            icon: svg(
+              foreground(layer, "on"),
+              "icons/x_mark_8.svg",
+              8,
+              8
+            ),
+          },
+          clicked: {
+            icon: svg(
+              foreground(layer, "base"),
+              "icons/x_mark_8.svg",
+              8,
+              8
+            ),
+          },
+        }),
+      dimensions: {
+        width: 280,
+        height: 280,
+      },
+    },
 
-        auth: {
-            content_width,
+    auth: {
+      content_width,
 
-            ctaButton,
+      ctaButton,
 
-            header: {
-                icon: svg(
-                    foreground(layer, "default"),
-                    "icons/zed_plus_copilot_32.svg",
-                    92,
-                    32
-                ),
-                container: {
-                    margin: {
-                        top: 35,
-                        bottom: 5,
-                        left: 0,
-                        right: 0,
-                    },
-                },
-            },
+      header: {
+        icon: svg(
+          foreground(layer, "default"),
+          "icons/zed_plus_copilot_32.svg",
+          92,
+          32
+        ),
+        container: {
+          margin: {
+            top: 35,
+            bottom: 5,
+            left: 0,
+            right: 0,
+          },
+        },
+      },
 
-            prompting: {
-                subheading: {
-                    ...text(layer, "sans", { size: "xs" }),
-                    margin: {
-                        top: 6,
-                        bottom: 12,
-                        left: 0,
-                        right: 0,
-                    },
-                },
+      prompting: {
+        subheading: {
+          ...text(layer, "sans", { size: "xs" }),
+          margin: {
+            top: 6,
+            bottom: 12,
+            left: 0,
+            right: 0,
+          },
+        },
 
-                hint: {
-                    ...text(layer, "sans", { size: "xs", color: "#838994" }),
-                    margin: {
-                        top: 6,
-                        bottom: 2,
-                    },
-                },
+        hint: {
+          ...text(layer, "sans", { size: "xs", color: "#838994" }),
+          margin: {
+            top: 6,
+            bottom: 2,
+          },
+        },
 
-                deviceCode: {
-                    text: text(layer, "mono", { size: "sm" }),
-                    cta: {
-                        ...ctaButton,
-                        background: background(colorScheme.lowest),
-                        border: border(colorScheme.lowest, "inverted"),
-                        padding: {
-                            top: 0,
-                            bottom: 0,
-                            left: 16,
-                            right: 16,
-                        },
-                        margin: {
-                            left: 16,
-                            right: 16,
-                        },
-                    },
-                    left: content_width / 2,
-                    leftContainer: {
-                        padding: {
-                            top: 3,
-                            bottom: 3,
-                            left: 0,
-                            right: 6,
-                        },
-                    },
-                    right: (content_width * 1) / 3,
-                    rightContainer: {
-                        border: border(colorScheme.lowest, "inverted", {
-                            bottom: false,
-                            right: false,
-                            top: false,
-                            left: true,
-                        }),
-                        padding: {
-                            top: 3,
-                            bottom: 5,
-                            left: 8,
-                            right: 0,
-                        },
-                        hover: {
-                            border: border(layer, "active", {
-                                bottom: false,
-                                right: false,
-                                top: false,
-                                left: true,
-                            }),
-                        },
-                    },
-                },
+        deviceCode: {
+          text: text(layer, "mono", { size: "sm" }),
+          cta: {
+            ...ctaButton,
+            background: background(colorScheme.lowest),
+            border: border(colorScheme.lowest, "inverted"),
+            padding: {
+              top: 0,
+              bottom: 0,
+              left: 16,
+              right: 16,
+            },
+            margin: {
+              left: 16,
+              right: 16,
+            },
+          },
+          left: content_width / 2,
+          leftContainer: {
+            padding: {
+              top: 3,
+              bottom: 3,
+              left: 0,
+              right: 6,
+            },
+          },
+          right: (content_width * 1) / 3,
+          rightContainer: interactive({
+            border: border(colorScheme.lowest, "inverted", {
+              bottom: false,
+              right: false,
+              top: false,
+              left: true,
+            }),
+            padding: {
+              top: 3,
+              bottom: 5,
+              left: 8,
+              right: 0,
+            }
+          }, {
+            hover: {
+              border: border(layer, "active", {
+                bottom: false,
+                right: false,
+                top: false,
+                left: true,
+              }),
             },
+          })
+        },
+      },
 
-            notAuthorized: {
-                subheading: {
-                    ...text(layer, "sans", { size: "xs" }),
+      notAuthorized: {
+        subheading: {
+          ...text(layer, "sans", { size: "xs" }),
 
-                    margin: {
-                        top: 16,
-                        bottom: 16,
-                        left: 0,
-                        right: 0,
-                    },
-                },
+          margin: {
+            top: 16,
+            bottom: 16,
+            left: 0,
+            right: 0,
+          },
+        },
 
-                warning: {
-                    ...text(layer, "sans", {
-                        size: "xs",
-                        color: foreground(layer, "warning"),
-                    }),
-                    border: border(layer, "warning"),
-                    background: background(layer, "warning"),
-                    cornerRadius: 2,
-                    padding: {
-                        top: 4,
-                        left: 4,
-                        bottom: 4,
-                        right: 4,
-                    },
-                    margin: {
-                        bottom: 16,
-                        left: 8,
-                        right: 8,
-                    },
-                },
-            },
+        warning: {
+          ...text(layer, "sans", {
+            size: "xs",
+            color: foreground(layer, "warning"),
+          }),
+          border: border(layer, "warning"),
+          background: background(layer, "warning"),
+          cornerRadius: 2,
+          padding: {
+            top: 4,
+            left: 4,
+            bottom: 4,
+            right: 4,
+          },
+          margin: {
+            bottom: 16,
+            left: 8,
+            right: 8,
+          },
+        },
+      },
 
-            authorized: {
-                subheading: {
-                    ...text(layer, "sans", { size: "xs" }),
+      authorized: {
+        subheading: {
+          ...text(layer, "sans", { size: "xs" }),
 
-                    margin: {
-                        top: 16,
-                        bottom: 16,
-                    },
-                },
+          margin: {
+            top: 16,
+            bottom: 16,
+          },
+        },
 
-                hint: {
-                    ...text(layer, "sans", { size: "xs", color: "#838994" }),
-                    margin: {
-                        top: 24,
-                        bottom: 4,
-                    },
-                },
-            },
+        hint: {
+          ...text(layer, "sans", { size: "xs", color: "#838994" }),
+          margin: {
+            top: 24,
+            bottom: 4,
+          },
         },
-    }
+      },
+    },
+  }
 }

styles/src/styleTree/editor.ts 🔗

@@ -4,275 +4,284 @@ import { background, border, borderColor, foreground, text } from "./components"
 import hoverPopover from "./hoverPopover"
 
 import { buildSyntax } from "../theme/syntax"
+import { interactive } from "./interactive"
+import { toggleable } from "./toggle"
 
 export default function editor(colorScheme: ColorScheme) {
-    const { isLight } = colorScheme
+  const { isLight } = colorScheme
 
-    let layer = colorScheme.highest
+  let layer = colorScheme.highest
 
-    const autocompleteItem = {
-        cornerRadius: 6,
-        padding: {
-            bottom: 2,
-            left: 6,
-            right: 6,
-            top: 2,
-        },
-    }
+  const autocompleteItem = {
+    cornerRadius: 6,
+    padding: {
+      bottom: 2,
+      left: 6,
+      right: 6,
+      top: 2,
+    },
+  }
 
-    function diagnostic(layer: Layer, styleSet: StyleSets) {
-        return {
-            textScaleFactor: 0.857,
-            header: {
-                border: border(layer, {
-                    top: true,
-                }),
-            },
-            message: {
-                text: text(layer, "sans", styleSet, "default", { size: "sm" }),
-                highlightText: text(layer, "sans", styleSet, "default", {
-                    size: "sm",
-                    weight: "bold",
-                }),
-            },
-        }
+  function diagnostic(layer: Layer, styleSet: StyleSets) {
+    return {
+      textScaleFactor: 0.857,
+      header: {
+        border: border(layer, {
+          top: true,
+        }),
+      },
+      message: {
+        text: text(layer, "sans", styleSet, "default", { size: "sm" }),
+        highlightText: text(layer, "sans", styleSet, "default", {
+          size: "sm",
+          weight: "bold",
+        }),
+      },
     }
+  }
 
-    const syntax = buildSyntax(colorScheme)
-
-    return {
-        textColor: syntax.primary.color,
-        background: background(layer),
-        activeLineBackground: withOpacity(background(layer, "on"), 0.75),
-        highlightedLineBackground: background(layer, "on"),
-        // Inline autocomplete suggestions, Co-pilot suggestions, etc.
-        suggestion: syntax.predictive,
-        codeActions: {
-            indicator: {
-                color: foreground(layer, "variant"),
+  const syntax = buildSyntax(colorScheme)
 
-                clicked: {
-                    color: foreground(layer, "base"),
-                },
-                hover: {
-                    color: foreground(layer, "on"),
-                },
-                active: {
-                    color: foreground(layer, "on"),
-                },
-            },
-            verticalScale: 0.55,
+  return {
+    textColor: syntax.primary.color,
+    background: background(layer),
+    activeLineBackground: withOpacity(background(layer, "on"), 0.75),
+    highlightedLineBackground: background(layer, "on"),
+    // Inline autocomplete suggestions, Co-pilot suggestions, etc.
+    suggestion: syntax.predictive,
+    codeActions: {
+      indicator: toggleable(interactive({
+        color: foreground(layer, "variant"),
+      }, {
+        clicked: {
+          color: foreground(layer, "base"),
         },
-        folds: {
-            iconMarginScale: 2.5,
-            foldedIcon: "icons/chevron_right_8.svg",
-            foldableIcon: "icons/chevron_down_8.svg",
-            indicator: {
-                color: foreground(layer, "variant"),
+        hover: {
+          color: foreground(layer, "on"),
+        },
+      }),
+        {
+          default: {
+            color: foreground(layer, "on"),
+          }
+        }),
 
-                clicked: {
-                    color: foreground(layer, "base"),
-                },
-                hover: {
-                    color: foreground(layer, "on"),
-                },
-                active: {
-                    color: foreground(layer, "on"),
-                },
-            },
-            ellipses: {
-                textColor: colorScheme.ramps.neutral(0.71).hex(),
-                cornerRadiusFactor: 0.15,
-                background: {
-                    // Copied from hover_popover highlight
-                    color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(),
+      verticalScale: 0.55,
+    },
+    folds: {
+      iconMarginScale: 2.5,
+      foldedIcon: "icons/chevron_right_8.svg",
+      foldableIcon: "icons/chevron_down_8.svg",
+      indicator: toggleable(interactive({
+        color: foreground(layer, "variant"),
+      }, {
+        clicked: {
+          color: foreground(layer, "base"),
+        },
+        hover: {
+          color: foreground(layer, "on"),
+        },
+      }),
+        {
+          default: {
+            color: foreground(layer, "on"),
+          }
+        }),
+      ellipses: {
+        textColor: colorScheme.ramps.neutral(0.71).hex(),
+        cornerRadiusFactor: 0.15,
+        background: {
+          // Copied from hover_popover highlight
+          default: { color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex() },
 
-                    hover: {
-                        color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
-                    },
+          hover: {
+            color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
+          },
 
-                    clicked: {
-                        color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(),
-                    },
-                },
-            },
-            foldBackground: foreground(layer, "variant"),
+          clicked: {
+            color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(),
+          },
         },
-        diff: {
-            deleted: isLight
-                ? colorScheme.ramps.red(0.5).hex()
-                : colorScheme.ramps.red(0.4).hex(),
-            modified: isLight
-                ? colorScheme.ramps.yellow(0.5).hex()
-                : colorScheme.ramps.yellow(0.5).hex(),
-            inserted: isLight
-                ? colorScheme.ramps.green(0.4).hex()
-                : colorScheme.ramps.green(0.5).hex(),
-            removedWidthEm: 0.275,
-            widthEm: 0.15,
-            cornerRadius: 0.05,
-        },
-        /** Highlights matching occurrences of what is under the cursor
-         * as well as matched brackets
-         */
-        documentHighlightReadBackground: withOpacity(
-            foreground(layer, "accent"),
-            0.1
+      },
+      foldBackground: foreground(layer, "variant"),
+    },
+    diff: {
+      deleted: isLight
+        ? colorScheme.ramps.red(0.5).hex()
+        : colorScheme.ramps.red(0.4).hex(),
+      modified: isLight
+        ? colorScheme.ramps.yellow(0.5).hex()
+        : colorScheme.ramps.yellow(0.5).hex(),
+      inserted: isLight
+        ? colorScheme.ramps.green(0.4).hex()
+        : colorScheme.ramps.green(0.5).hex(),
+      removedWidthEm: 0.275,
+      widthEm: 0.15,
+      cornerRadius: 0.05,
+    },
+    /** Highlights matching occurrences of what is under the cursor
+     * as well as matched brackets
+     */
+    documentHighlightReadBackground: withOpacity(
+      foreground(layer, "accent"),
+      0.1
+    ),
+    documentHighlightWriteBackground: colorScheme.ramps
+      .neutral(0.5)
+      .alpha(0.4)
+      .hex(), // TODO: This was blend * 2
+    errorColor: background(layer, "negative"),
+    gutterBackground: background(layer),
+    gutterPaddingFactor: 3.5,
+    lineNumber: withOpacity(foreground(layer), 0.35),
+    lineNumberActive: foreground(layer),
+    renameFade: 0.6,
+    unnecessaryCodeFade: 0.5,
+    selection: colorScheme.players[0],
+    whitespace: colorScheme.ramps.neutral(0.5).hex(),
+    guestSelections: [
+      colorScheme.players[1],
+      colorScheme.players[2],
+      colorScheme.players[3],
+      colorScheme.players[4],
+      colorScheme.players[5],
+      colorScheme.players[6],
+      colorScheme.players[7],
+    ],
+    autocomplete: {
+      background: background(colorScheme.middle),
+      cornerRadius: 8,
+      padding: 4,
+      margin: {
+        left: -14,
+      },
+      border: border(colorScheme.middle),
+      shadow: colorScheme.popoverShadow,
+      matchHighlight: foreground(colorScheme.middle, "accent"),
+      item: autocompleteItem,
+      hoveredItem: {
+        ...autocompleteItem,
+        matchHighlight: foreground(
+          colorScheme.middle,
+          "accent",
+          "hovered"
         ),
-        documentHighlightWriteBackground: colorScheme.ramps
-            .neutral(0.5)
-            .alpha(0.4)
-            .hex(), // TODO: This was blend * 2
-        errorColor: background(layer, "negative"),
-        gutterBackground: background(layer),
-        gutterPaddingFactor: 3.5,
-        lineNumber: withOpacity(foreground(layer), 0.35),
-        lineNumberActive: foreground(layer),
-        renameFade: 0.6,
-        unnecessaryCodeFade: 0.5,
-        selection: colorScheme.players[0],
-        whitespace: colorScheme.ramps.neutral(0.5).hex(),
-        guestSelections: [
-            colorScheme.players[1],
-            colorScheme.players[2],
-            colorScheme.players[3],
-            colorScheme.players[4],
-            colorScheme.players[5],
-            colorScheme.players[6],
-            colorScheme.players[7],
-        ],
-        autocomplete: {
-            background: background(colorScheme.middle),
-            cornerRadius: 8,
-            padding: 4,
-            margin: {
-                left: -14,
-            },
-            border: border(colorScheme.middle),
-            shadow: colorScheme.popoverShadow,
-            matchHighlight: foreground(colorScheme.middle, "accent"),
-            item: autocompleteItem,
-            hoveredItem: {
-                ...autocompleteItem,
-                matchHighlight: foreground(
-                    colorScheme.middle,
-                    "accent",
-                    "hovered"
-                ),
-                background: background(colorScheme.middle, "hovered"),
-            },
-            selectedItem: {
-                ...autocompleteItem,
-                matchHighlight: foreground(
-                    colorScheme.middle,
-                    "accent",
-                    "active"
-                ),
-                background: background(colorScheme.middle, "active"),
-            },
-        },
-        diagnosticHeader: {
-            background: background(colorScheme.middle),
-            iconWidthFactor: 1.5,
-            textScaleFactor: 0.857,
-            border: border(colorScheme.middle, {
-                bottom: true,
-                top: true,
-            }),
-            code: {
-                ...text(colorScheme.middle, "mono", { size: "sm" }),
-                margin: {
-                    left: 10,
-                },
-            },
-            source: {
-                text: text(colorScheme.middle, "sans", {
-                    size: "sm",
-                    weight: "bold",
-                }),
-            },
-            message: {
-                highlightText: text(colorScheme.middle, "sans", {
-                    size: "sm",
-                    weight: "bold",
-                }),
-                text: text(colorScheme.middle, "sans", { size: "sm" }),
-            },
-        },
-        diagnosticPathHeader: {
-            background: background(colorScheme.middle),
-            textScaleFactor: 0.857,
-            filename: text(colorScheme.middle, "mono", { size: "sm" }),
-            path: {
-                ...text(colorScheme.middle, "mono", { size: "sm" }),
-                margin: {
-                    left: 12,
-                },
-            },
-        },
-        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,
-        },
-        jumpIcon: {
-            color: foreground(layer, "on"),
-            iconWidth: 20,
-            buttonWidth: 20,
-            cornerRadius: 6,
-            padding: {
-                top: 6,
-                bottom: 6,
-                left: 6,
-                right: 6,
-            },
-            hover: {
-                background: background(layer, "on", "hovered"),
-            },
+        background: background(colorScheme.middle, "hovered"),
+      },
+      selectedItem: {
+        ...autocompleteItem,
+        matchHighlight: foreground(
+          colorScheme.middle,
+          "accent",
+          "active"
+        ),
+        background: background(colorScheme.middle, "active"),
+      },
+    },
+    diagnosticHeader: {
+      background: background(colorScheme.middle),
+      iconWidthFactor: 1.5,
+      textScaleFactor: 0.857,
+      border: border(colorScheme.middle, {
+        bottom: true,
+        top: true,
+      }),
+      code: {
+        ...text(colorScheme.middle, "mono", { size: "sm" }),
+        margin: {
+          left: 10,
         },
-        scrollbar: {
-            width: 12,
-            minHeightFactor: 1.0,
-            track: {
-                border: border(layer, "variant", { left: true }),
-            },
-            thumb: {
-                background: withOpacity(background(layer, "inverted"), 0.3),
-                border: {
-                    width: 1,
-                    color: borderColor(layer, "variant"),
-                    top: false,
-                    right: true,
-                    left: true,
-                    bottom: false,
-                },
-            },
-            git: {
-                deleted: isLight
-                    ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
-                    : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
-                modified: isLight
-                    ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
-                    : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
-                inserted: isLight
-                    ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
-                    : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
-            },
+      },
+      source: {
+        text: text(colorScheme.middle, "sans", {
+          size: "sm",
+          weight: "bold",
+        }),
+      },
+      message: {
+        highlightText: text(colorScheme.middle, "sans", {
+          size: "sm",
+          weight: "bold",
+        }),
+        text: text(colorScheme.middle, "sans", { size: "sm" }),
+      },
+    },
+    diagnosticPathHeader: {
+      background: background(colorScheme.middle),
+      textScaleFactor: 0.857,
+      filename: text(colorScheme.middle, "mono", { size: "sm" }),
+      path: {
+        ...text(colorScheme.middle, "mono", { size: "sm" }),
+        margin: {
+          left: 12,
         },
-        compositionMark: {
-            underline: {
-                thickness: 1.0,
-                color: borderColor(layer),
-            },
+      },
+    },
+    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,
+    },
+    jumpIcon: interactive({
+      color: foreground(layer, "on"),
+      iconWidth: 20,
+      buttonWidth: 20,
+      cornerRadius: 6,
+      padding: {
+        top: 6,
+        bottom: 6,
+        left: 6,
+        right: 6,
+      }
+    }, {
+      hover: {
+        background: background(layer, "on", "hovered"),
+      }
+    }),
+
+    scrollbar: {
+      width: 12,
+      minHeightFactor: 1.0,
+      track: {
+        border: border(layer, "variant", { left: true }),
+      },
+      thumb: {
+        background: withOpacity(background(layer, "inverted"), 0.3),
+        border: {
+          width: 1,
+          color: borderColor(layer, "variant"),
+          top: false,
+          right: true,
+          left: true,
+          bottom: false,
         },
-        syntax,
-    }
+      },
+      git: {
+        deleted: isLight
+          ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
+          : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
+        modified: isLight
+          ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
+          : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
+        inserted: isLight
+          ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
+          : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
+      },
+    },
+    compositionMark: {
+      underline: {
+        thickness: 1.0,
+        color: borderColor(layer),
+      },
+    },
+    syntax,
+  }
 }

styles/src/styleTree/picker.ts 🔗

@@ -1,82 +1,86 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { background, border, text } from "./components"
+import { toggleable } from "./toggle"
+import { interactive } from "./interactive"
 
 export default function picker(colorScheme: ColorScheme): any {
-    let layer = colorScheme.lowest
-    const container = {
-        background: background(layer),
-        border: border(layer),
-        shadow: colorScheme.modalShadow,
-        cornerRadius: 12,
-        padding: {
-            bottom: 4,
-        },
-    }
-    const inputEditor = {
-        placeholderText: text(layer, "sans", "on", "disabled"),
-        selection: colorScheme.players[0],
-        text: text(layer, "mono", "on"),
-        border: border(layer, { bottom: true }),
-        padding: {
-            bottom: 8,
-            left: 16,
-            right: 16,
-            top: 8,
-        },
-        margin: {
-            bottom: 4,
-        },
-    }
-    const emptyInputEditor: any = { ...inputEditor }
-    delete emptyInputEditor.border
-    delete emptyInputEditor.margin
+  let layer = colorScheme.lowest
+  const container = {
+    background: background(layer),
+    border: border(layer),
+    shadow: colorScheme.modalShadow,
+    cornerRadius: 12,
+    padding: {
+      bottom: 4,
+    },
+  }
+  const inputEditor = {
+    placeholderText: text(layer, "sans", "on", "disabled"),
+    selection: colorScheme.players[0],
+    text: text(layer, "mono", "on"),
+    border: border(layer, { bottom: true }),
+    padding: {
+      bottom: 8,
+      left: 16,
+      right: 16,
+      top: 8,
+    },
+    margin: {
+      bottom: 4,
+    },
+  }
+  const emptyInputEditor: any = { ...inputEditor }
+  delete emptyInputEditor.border
+  delete emptyInputEditor.margin
 
-    return {
-        ...container,
-        emptyContainer: {
-            ...container,
-            padding: {},
-        },
-        item: {
-            padding: {
-                bottom: 4,
-                left: 12,
-                right: 12,
-                top: 4,
-            },
-            margin: {
-                top: 1,
-                left: 4,
-                right: 4,
-            },
-            cornerRadius: 8,
-            text: text(layer, "sans", "variant"),
-            highlightText: text(layer, "sans", "accent", { weight: "bold" }),
-            active: {
-                background: withOpacity(
-                    background(layer, "base", "active"),
-                    0.5
-                ),
-                text: text(layer, "sans", "base", "active"),
-                highlightText: text(layer, "sans", "accent", {
-                    weight: "bold",
-                }),
-            },
-            hover: {
-                background: withOpacity(background(layer, "hovered"), 0.5),
-            },
-        },
-        inputEditor,
-        emptyInputEditor,
-        noMatches: {
-            text: text(layer, "sans", "variant"),
-            padding: {
-                bottom: 8,
-                left: 16,
-                right: 16,
-                top: 8,
-            },
-        },
-    }
+  return {
+    ...container,
+    emptyContainer: {
+      ...container,
+      padding: {},
+    },
+    item: toggleable(interactive({
+      padding: {
+        bottom: 4,
+        left: 12,
+        right: 12,
+        top: 4,
+      },
+      margin: {
+        top: 1,
+        left: 4,
+        right: 4,
+      },
+      cornerRadius: 8,
+      text: text(layer, "sans", "variant"),
+      highlightText: text(layer, "sans", "accent", { weight: "bold" }),
+    }, {
+      hover: {
+        background: withOpacity(background(layer, "hovered"), 0.5),
+      }
+    }),
+      {
+        default: {
+          background: withOpacity(
+            background(layer, "base", "active"),
+            0.5
+          ),
+          //text: text(layer, "sans", "base", "active"),
+        }
+      }),
+
+
+    inputEditor,
+    emptyInputEditor,
+    noMatches: {
+      text: text(layer, "sans", "variant"),
+      padding: {
+        bottom: 8,
+        left: 16,
+        right: 16,
+        top: 8,
+      },
+    },
+  }
 }

styles/src/styleTree/projectPanel.ts 🔗

@@ -1,107 +1,119 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { background, border, foreground, text } from "./components"
-
+import { interactive } from "./interactive"
+import { toggleable } from "./toggle"
 export default function projectPanel(colorScheme: ColorScheme) {
-    const { isLight } = colorScheme
+  const { isLight } = colorScheme
 
-    let layer = colorScheme.middle
+  let layer = colorScheme.middle
 
-    let baseEntry = {
-        height: 22,
-        iconColor: foreground(layer, "variant"),
-        iconSize: 7,
-        iconSpacing: 5,
-    }
+  let baseEntry = {
+    height: 22,
+    iconColor: foreground(layer, "variant"),
+    iconSize: 7,
+    iconSpacing: 5,
+  }
 
-    let status = {
-        git: {
-            modified: isLight
-                ? colorScheme.ramps.yellow(0.6).hex()
-                : colorScheme.ramps.yellow(0.5).hex(),
-            inserted: isLight
-                ? colorScheme.ramps.green(0.45).hex()
-                : colorScheme.ramps.green(0.5).hex(),
-            conflict: isLight
-                ? colorScheme.ramps.red(0.6).hex()
-                : colorScheme.ramps.red(0.5).hex(),
-        },
-    }
+  let status = {
+    git: {
+      modified: isLight
+        ? colorScheme.ramps.yellow(0.6).hex()
+        : colorScheme.ramps.yellow(0.5).hex(),
+      inserted: isLight
+        ? colorScheme.ramps.green(0.45).hex()
+        : colorScheme.ramps.green(0.5).hex(),
+      conflict: isLight
+        ? colorScheme.ramps.red(0.6).hex()
+        : colorScheme.ramps.red(0.5).hex(),
+    },
+  }
 
-    let entry = {
-        ...baseEntry,
-        text: text(layer, "mono", "variant", { size: "sm" }),
-        hover: {
-            background: background(layer, "variant", "hovered"),
-        },
-        active: {
-            background: colorScheme.isLight
-                ? withOpacity(background(layer, "active"), 0.5)
-                : background(layer, "active"),
-            text: text(layer, "mono", "active", { size: "sm" }),
-        },
-        activeHover: {
-            background: background(layer, "active"),
-            text: text(layer, "mono", "active", { size: "sm" }),
-        },
-        status,
-    }
+  let entry = toggleable(interactive({
+    ...baseEntry,
+    text: text(layer, "mono", "variant", { size: "sm" }),
+    status,
+  },
+    {
+      hover: {
+        background: background(layer, "variant", "hovered"),
+      }
+    }),
+    {
+      default: {
+        /*background: colorScheme.isLight
+          ? withOpacity(background(layer, "active"), 0.5)
+          : background(layer, "active") ,*/ // todo posiewic
+        text: text(layer, "mono", "active", { size: "sm" }),
+      },
+      hover: {
+        //background: background(layer, "active"),
+        text: text(layer, "mono", "active", { size: "sm" }),
+      },
 
-    return {
-        openProjectButton: {
-            background: background(layer),
-            border: border(layer, "active"),
-            cornerRadius: 4,
-            margin: {
-                top: 16,
-                left: 16,
-                right: 16,
-            },
-            padding: {
-                top: 3,
-                bottom: 3,
-                left: 7,
-                right: 7,
-            },
-            ...text(layer, "sans", "default", { size: "sm" }),
-            hover: {
-                ...text(layer, "sans", "default", { size: "sm" }),
-                background: background(layer, "hovered"),
-                border: border(layer, "active"),
-            },
-        },
-        background: background(layer),
-        padding: { left: 6, right: 6, top: 0, bottom: 6 },
-        indentWidth: 12,
-        entry,
-        draggedEntry: {
-            ...baseEntry,
-            text: text(layer, "mono", "on", { size: "sm" }),
-            background: withOpacity(background(layer, "on"), 0.9),
-            border: border(layer),
-            status,
-        },
-        ignoredEntry: {
-            ...entry,
-            iconColor: foreground(layer, "disabled"),
-            text: text(layer, "mono", "disabled"),
-            active: {
-                ...entry.active,
-                iconColor: foreground(layer, "variant"),
-            },
-        },
-        cutEntry: {
-            ...entry,
-            text: text(layer, "mono", "disabled"),
-            active: {
-                background: background(layer, "active"),
-                text: text(layer, "mono", "disabled", { size: "sm" }),
-            },
-        },
-        filenameEditor: {
-            background: background(layer, "on"),
-            text: text(layer, "mono", "on", { size: "sm" }),
-            selection: colorScheme.players[0],
+    });
+
+  return {
+    openProjectButton: interactive({
+      background: background(layer),
+      border: border(layer, "active"),
+      cornerRadius: 4,
+      margin: {
+        top: 16,
+        left: 16,
+        right: 16,
+      },
+      padding: {
+        top: 3,
+        bottom: 3,
+        left: 7,
+        right: 7,
+      },
+      ...text(layer, "sans", "default", { size: "sm" })
+    }, {
+      hover: {
+        ...text(layer, "sans", "default", { size: "sm" }),
+        background: background(layer, "hovered"),
+        border: border(layer, "active"),
+      },
+    }),
+    background: background(layer),
+    padding: { left: 6, right: 6, top: 0, bottom: 6 },
+    indentWidth: 12,
+    entry,
+    draggedEntry: {
+      ...baseEntry,
+      text: text(layer, "mono", "on", { size: "sm" }),
+      background: withOpacity(background(layer, "on"), 0.9),
+      border: border(layer),
+      status,
+    },
+    ignoredEntry: {
+      ...entry,
+      iconColor: foreground(layer, "disabled"),
+      text: text(layer, "mono", "disabled"),
+      active: {
+        ...entry.active,
+        iconColor: foreground(layer, "variant"),
+      },
+    },
+    cutEntry: {
+      ...entry,
+      text: text(layer, "mono", "disabled"),
+      active: {
+        ...entry.active,
+        default: {
+          ...entry.active.default,
+          background: background(layer, "active"),
+          text: text(layer, "mono", "disabled", { size: "sm" }),
         },
-    }
+
+      },
+    },
+    filenameEditor: {
+      background: background(layer, "on"),
+      text: text(layer, "mono", "on", { size: "sm" }),
+      selection: colorScheme.players[0],
+    },
+  }
 }

styles/src/styleTree/statusBar.ts 🔗

@@ -1,126 +1,135 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, foreground, text } from "./components"
-
+import { interactive } from "./interactive"
+import { toggleable } from "./toggle"
 export default function statusBar(colorScheme: ColorScheme) {
-    let layer = colorScheme.lowest
+  let layer = colorScheme.lowest
 
-    const statusContainer = {
-        cornerRadius: 6,
-        padding: { top: 3, bottom: 3, left: 6, right: 6 },
-    }
+  const statusContainer = {
+    cornerRadius: 6,
+    padding: { top: 3, bottom: 3, left: 6, right: 6 },
+  }
 
-    const diagnosticStatusContainer = {
-        cornerRadius: 6,
-        padding: { top: 1, bottom: 1, left: 6, right: 6 },
-    }
+  const diagnosticStatusContainer = {
+    cornerRadius: 6,
+    padding: { top: 1, bottom: 1, left: 6, right: 6 },
+  }
 
-    return {
-        height: 30,
-        itemSpacing: 8,
-        padding: {
-            top: 1,
-            bottom: 1,
-            left: 6,
-            right: 6,
-        },
-        border: border(layer, { top: true, overlay: true }),
-        cursorPosition: text(layer, "sans", "variant"),
-        activeLanguage: {
-            padding: { left: 6, right: 6 },
-            ...text(layer, "sans", "variant"),
-            hover: {
-                ...text(layer, "sans", "on"),
-            },
-        },
-        autoUpdateProgressMessage: text(layer, "sans", "variant"),
-        autoUpdateDoneMessage: text(layer, "sans", "variant"),
-        lspStatus: {
-            ...diagnosticStatusContainer,
-            iconSpacing: 4,
-            iconWidth: 14,
-            height: 18,
-            message: text(layer, "sans"),
-            iconColor: foreground(layer),
-            hover: {
-                message: text(layer, "sans"),
-                iconColor: foreground(layer),
-                background: background(layer, "hovered"),
-            },
-        },
-        diagnosticMessage: {
-            ...text(layer, "sans"),
-            hover: text(layer, "sans", "hovered"),
+  return {
+    height: 30,
+    itemSpacing: 8,
+    padding: {
+      top: 1,
+      bottom: 1,
+      left: 6,
+      right: 6,
+    },
+    border: border(layer, { top: true, overlay: true }),
+    cursorPosition: text(layer, "sans", "variant"),
+    activeLanguage: interactive({
+      padding: { left: 6, right: 6 },
+      ...text(layer, "sans", "variant")
+    },
+      {
+        hover: {
+          ...text(layer, "sans", "on"),
+        }
+      },
+    ),
+    autoUpdateProgressMessage: text(layer, "sans", "variant"),
+    autoUpdateDoneMessage: text(layer, "sans", "variant"),
+    lspStatus: interactive({
+      ...diagnosticStatusContainer,
+      iconSpacing: 4,
+      iconWidth: 14,
+      height: 18,
+      message: text(layer, "sans"),
+      iconColor: foreground(layer)
+    },
+      {
+        hover: {
+          message: text(layer, "sans"),
+          iconColor: foreground(layer),
+          background: background(layer, "hovered"),
+        }
+      }),
+    diagnosticMessage: interactive({
+      ...text(layer, "sans")
+    },
+      { hover: text(layer, "sans", "hovered") },
+    ),
+    diagnosticSummary:
+      interactive({
+        height: 20,
+        iconWidth: 16,
+        iconSpacing: 2,
+        summarySpacing: 6,
+        text: text(layer, "sans", { size: "sm" }),
+        iconColorOk: foreground(layer, "variant"),
+        iconColorWarning: foreground(layer, "warning"),
+        iconColorError: foreground(layer, "negative"),
+        containerOk: {
+          cornerRadius: 6,
+          padding: { top: 3, bottom: 3, left: 7, right: 7 },
         },
-        diagnosticSummary: {
-            height: 20,
-            iconWidth: 16,
-            iconSpacing: 2,
-            summarySpacing: 6,
-            text: text(layer, "sans", { size: "sm" }),
-            iconColorOk: foreground(layer, "variant"),
-            iconColorWarning: foreground(layer, "warning"),
-            iconColorError: foreground(layer, "negative"),
-            containerOk: {
-                cornerRadius: 6,
-                padding: { top: 3, bottom: 3, left: 7, right: 7 },
-            },
-            containerWarning: {
-                ...diagnosticStatusContainer,
-                background: background(layer, "warning"),
-                border: border(layer, "warning"),
-            },
-            containerError: {
-                ...diagnosticStatusContainer,
-                background: background(layer, "negative"),
-                border: border(layer, "negative"),
-            },
-            hover: {
-                iconColorOk: foreground(layer, "on"),
-                containerOk: {
-                    cornerRadius: 6,
-                    padding: { top: 3, bottom: 3, left: 7, right: 7 },
-                    background: background(layer, "on", "hovered"),
-                },
-                containerWarning: {
-                    ...diagnosticStatusContainer,
-                    background: background(layer, "warning", "hovered"),
-                    border: border(layer, "warning", "hovered"),
-                },
-                containerError: {
-                    ...diagnosticStatusContainer,
-                    background: background(layer, "negative", "hovered"),
-                    border: border(layer, "negative", "hovered"),
-                },
-            },
+        containerWarning: {
+          ...diagnosticStatusContainer,
+          background: background(layer, "warning"),
+          border: border(layer, "warning"),
         },
-        panelButtons: {
-            groupLeft: {},
-            groupBottom: {},
-            groupRight: {},
-            button: {
-                ...statusContainer,
-                iconSize: 16,
-                iconColor: foreground(layer, "variant"),
-                label: {
-                    margin: { left: 6 },
-                    ...text(layer, "sans", { size: "sm" }),
-                },
-                hover: {
-                    iconColor: foreground(layer, "hovered"),
-                    background: background(layer, "variant"),
-                },
-                active: {
-                    iconColor: foreground(layer, "active"),
-                    background: background(layer, "active"),
-                },
-            },
-            badge: {
-                cornerRadius: 3,
-                padding: 2,
-                margin: { bottom: -1, right: -1 },
-                border: border(layer),
-                background: background(layer, "accent"),
-            },
+        containerError: {
+          ...diagnosticStatusContainer,
+          background: background(layer, "negative"),
+          border: border(layer, "negative"),
+        }
+      }, {
+        hover: {
+          iconColorOk: foreground(layer, "on"),
+          containerOk: {
+            background: background(layer, "on", "hovered"),
+          },
+          containerWarning: {
+            background: background(layer, "warning", "hovered"),
+            border: border(layer, "warning", "hovered"),
+          },
+          containerError: {
+            background: background(layer, "negative", "hovered"),
+            border: border(layer, "negative", "hovered"),
+          }
+        }
+      }
+      ),
+    panelButtons: {
+      groupLeft: {},
+      groupBottom: {},
+      groupRight: {},
+      button: toggleable(interactive({
+        ...statusContainer,
+        iconSize: 16,
+        iconColor: foreground(layer, "variant"),
+        label: {
+          margin: { left: 6 },
+          ...text(layer, "sans", { size: "sm" }),
         },
-    }
+      }, {
+        hover: {
+          iconColor: foreground(layer, "hovered"),
+          background: background(layer, "variant"),
+        }
+      }),
+        {
+          default: {
+            iconColor: foreground(layer, "active"),
+            background: background(layer, "active"),
+          }
+        }),
+      badge: {
+        cornerRadius: 3,
+        padding: 2,
+        margin: { bottom: -1, right: -1 },
+        border: border(layer),
+        background: background(layer, "accent"),
+      },
+    },
+  }
 }

styles/src/styleTree/tabBar.ts 🔗

@@ -1,109 +1,116 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { text, border, background, foreground } from "./components"
+import { toggleable } from "./toggle"
+import { interactive } from "./interactive"
 
 export default function tabBar(colorScheme: ColorScheme) {
-    const height = 32
+  const height = 32
 
-    let activeLayer = colorScheme.highest
-    let layer = colorScheme.middle
+  let activeLayer = colorScheme.highest
+  let layer = colorScheme.middle
 
-    const tab = {
-        height,
-        text: text(layer, "sans", "variant", { size: "sm" }),
-        background: background(layer),
-        border: border(layer, {
-            right: true,
-            bottom: true,
-            overlay: true,
-        }),
-        padding: {
-            left: 8,
-            right: 12,
-        },
-        spacing: 8,
+  const tab = {
+    height,
+    text: text(layer, "sans", "variant", { size: "sm" }),
+    background: background(layer),
+    border: border(layer, {
+      right: true,
+      bottom: true,
+      overlay: true,
+    }),
+    padding: {
+      left: 8,
+      right: 12,
+    },
+    spacing: 8,
 
-        // Tab type icons (e.g. Project Search)
-        typeIconWidth: 14,
+    // Tab type icons (e.g. Project Search)
+    typeIconWidth: 14,
 
-        // Close icons
-        closeIconWidth: 8,
-        iconClose: foreground(layer, "variant"),
-        iconCloseActive: foreground(layer, "hovered"),
+    // Close icons
+    closeIconWidth: 8,
+    iconClose: foreground(layer, "variant"),
+    iconCloseActive: foreground(layer, "hovered"),
 
-        // Indicators
-        iconConflict: foreground(layer, "warning"),
-        iconDirty: foreground(layer, "accent"),
+    // Indicators
+    iconConflict: foreground(layer, "warning"),
+    iconDirty: foreground(layer, "accent"),
 
-        // When two tabs of the same name are open, a label appears next to them
-        description: {
-            margin: { left: 8 },
-            ...text(layer, "sans", "disabled", { size: "2xs" }),
-        },
-    }
+    // When two tabs of the same name are open, a label appears next to them
+    description: {
+      margin: { left: 8 },
+      ...text(layer, "sans", "disabled", { size: "2xs" }),
+    },
+  }
 
-    const activePaneActiveTab = {
-        ...tab,
-        background: background(activeLayer),
-        text: text(activeLayer, "sans", "active", { size: "sm" }),
-        border: {
-            ...tab.border,
-            bottom: false,
-        },
-    }
+  const activePaneActiveTab = {
+    ...tab,
+    background: background(activeLayer),
+    text: text(activeLayer, "sans", "active", { size: "sm" }),
+    border: {
+      ...tab.border,
+      bottom: false,
+    },
+  }
 
-    const inactivePaneInactiveTab = {
-        ...tab,
-        background: background(layer),
-        text: text(layer, "sans", "variant", { size: "sm" }),
-    }
+  const inactivePaneInactiveTab = {
+    ...tab,
+    background: background(layer),
+    text: text(layer, "sans", "variant", { size: "sm" }),
+  }
 
-    const inactivePaneActiveTab = {
-        ...tab,
-        background: background(activeLayer),
-        text: text(layer, "sans", "variant", { size: "sm" }),
-        border: {
-            ...tab.border,
-            bottom: false,
-        },
-    }
+  const inactivePaneActiveTab = {
+    ...tab,
+    background: background(activeLayer),
+    text: text(layer, "sans", "variant", { size: "sm" }),
+    border: {
+      ...tab.border,
+      bottom: false,
+    },
+  }
 
-    const draggedTab = {
-        ...activePaneActiveTab,
-        background: withOpacity(tab.background, 0.9),
-        border: undefined as any,
-        shadow: colorScheme.popoverShadow,
-    }
+  const draggedTab = {
+    ...activePaneActiveTab,
+    background: withOpacity(tab.background, 0.9),
+    border: undefined as any,
+    shadow: colorScheme.popoverShadow,
+  }
 
-    return {
-        height,
-        background: background(layer),
-        activePane: {
-            activeTab: activePaneActiveTab,
-            inactiveTab: tab,
-        },
-        inactivePane: {
-            activeTab: inactivePaneActiveTab,
-            inactiveTab: inactivePaneInactiveTab,
-        },
-        draggedTab,
-        paneButton: {
-            color: foreground(layer, "variant"),
-            iconWidth: 12,
-            buttonWidth: activePaneActiveTab.height,
-            hover: {
-                color: foreground(layer, "hovered"),
-            },
-            active: {
-                color: foreground(layer, "accent"),
-            },
-        },
-        paneButtonContainer: {
-            background: tab.background,
-            border: {
-                ...tab.border,
-                right: false,
-            },
-        },
-    }
+  return {
+    height,
+    background: background(layer),
+    activePane: {
+      activeTab: activePaneActiveTab,
+      inactiveTab: tab,
+    },
+    inactivePane: {
+      activeTab: inactivePaneActiveTab,
+      inactiveTab: inactivePaneInactiveTab,
+    },
+    draggedTab,
+    paneButton: toggleable(interactive({
+      color: foreground(layer, "variant"),
+      iconWidth: 12,
+      buttonWidth: activePaneActiveTab.height,
+    },
+      {
+        hover: {
+          color: foreground(layer, "hovered"),
+        }
+      }),
+      {
+        default: {
+          color: foreground(layer, "accent"),
+        }
+      },
+    ),
+    paneButtonContainer: {
+      background: tab.background,
+      border: {
+        ...tab.border,
+        right: false,
+      },
+    },
+  }
 }

styles/src/styleTree/welcome.ts 🔗

@@ -1,129 +1,131 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import {
-    border,
-    background,
-    foreground,
-    text,
-    TextProperties,
-    svg,
+  border,
+  background,
+  foreground,
+  text,
+  TextProperties,
+  svg,
 } from "./components"
+import { interactive } from "./interactive"
 
 export default function welcome(colorScheme: ColorScheme) {
-    let layer = colorScheme.highest
+  let layer = colorScheme.highest
 
-    let checkboxBase = {
-        cornerRadius: 4,
-        padding: {
-            left: 3,
-            right: 3,
-            top: 3,
-            bottom: 3,
-        },
-        // shadow: colorScheme.popoverShadow,
-        border: border(layer),
-        margin: {
-            right: 8,
-            top: 5,
-            bottom: 5,
-        },
-    }
+  let checkboxBase = {
+    cornerRadius: 4,
+    padding: {
+      left: 3,
+      right: 3,
+      top: 3,
+      bottom: 3,
+    },
+    // shadow: colorScheme.popoverShadow,
+    border: border(layer),
+    margin: {
+      right: 8,
+      top: 5,
+      bottom: 5,
+    },
+  }
 
-    let interactive_text_size: TextProperties = { size: "sm" }
+  let interactive_text_size: TextProperties = { size: "sm" }
 
-    return {
-        pageWidth: 320,
-        logo: svg(foreground(layer, "default"), "icons/logo_96.svg", 64, 64),
-        logoSubheading: {
-            ...text(layer, "sans", "variant", { size: "md" }),
-            margin: {
-                top: 10,
-                bottom: 7,
-            },
-        },
-        buttonGroup: {
-            margin: {
-                top: 8,
-                bottom: 16,
-            },
-        },
-        headingGroup: {
-            margin: {
-                top: 8,
-                bottom: 12,
-            },
-        },
-        checkboxGroup: {
-            border: border(layer, "variant"),
-            background: withOpacity(background(layer, "hovered"), 0.25),
-            cornerRadius: 4,
-            padding: {
-                left: 12,
-                top: 2,
-                bottom: 2,
-            },
-        },
-        button: {
-            background: background(layer),
-            border: border(layer, "active"),
-            cornerRadius: 4,
-            margin: {
-                top: 4,
-                bottom: 4,
-            },
-            padding: {
-                top: 3,
-                bottom: 3,
-                left: 7,
-                right: 7,
-            },
-            ...text(layer, "sans", "default", interactive_text_size),
-            hover: {
-                ...text(layer, "sans", "default", interactive_text_size),
-                background: background(layer, "hovered"),
-                border: border(layer, "active"),
-            },
-        },
-        usageNote: {
-            ...text(layer, "sans", "variant", { size: "2xs" }),
-            padding: {
-                top: -4,
-            },
-        },
-        checkboxContainer: {
-            margin: {
-                top: 4,
-            },
-            padding: {
-                bottom: 8,
-            },
-        },
-        checkbox: {
-            label: {
-                ...text(layer, "sans", interactive_text_size),
-                // Also supports margin, container, border, etc.
-            },
-            icon: svg(foreground(layer, "on"), "icons/check_12.svg", 12, 12),
-            default: {
-                ...checkboxBase,
-                background: background(layer, "default"),
-                border: border(layer, "active"),
-            },
-            checked: {
-                ...checkboxBase,
-                background: background(layer, "hovered"),
-                border: border(layer, "active"),
-            },
-            hovered: {
-                ...checkboxBase,
-                background: background(layer, "hovered"),
-                border: border(layer, "active"),
-            },
-            hoveredAndChecked: {
-                ...checkboxBase,
-                background: background(layer, "hovered"),
-                border: border(layer, "active"),
-            },
-        },
-    }
+  return {
+    pageWidth: 320,
+    logo: svg(foreground(layer, "default"), "icons/logo_96.svg", 64, 64),
+    logoSubheading: {
+      ...text(layer, "sans", "variant", { size: "md" }),
+      margin: {
+        top: 10,
+        bottom: 7,
+      },
+    },
+    buttonGroup: {
+      margin: {
+        top: 8,
+        bottom: 16,
+      },
+    },
+    headingGroup: {
+      margin: {
+        top: 8,
+        bottom: 12,
+      },
+    },
+    checkboxGroup: {
+      border: border(layer, "variant"),
+      background: withOpacity(background(layer, "hovered"), 0.25),
+      cornerRadius: 4,
+      padding: {
+        left: 12,
+        top: 2,
+        bottom: 2,
+      },
+    },
+    button: interactive({
+      background: background(layer),
+      border: border(layer, "active"),
+      cornerRadius: 4,
+      margin: {
+        top: 4,
+        bottom: 4,
+      },
+      padding: {
+        top: 3,
+        bottom: 3,
+        left: 7,
+        right: 7,
+      },
+      ...text(layer, "sans", "default", interactive_text_size)
+    }, {
+      hover: {
+        ...text(layer, "sans", "default", interactive_text_size),
+        background: background(layer, "hovered"),
+      }
+    }),
+
+    usageNote: {
+      ...text(layer, "sans", "variant", { size: "2xs" }),
+      padding: {
+        top: -4,
+      },
+    },
+    checkboxContainer: {
+      margin: {
+        top: 4,
+      },
+      padding: {
+        bottom: 8,
+      },
+    },
+    checkbox: {
+      label: {
+        ...text(layer, "sans", interactive_text_size),
+        // Also supports margin, container, border, etc.
+      },
+      icon: svg(foreground(layer, "on"), "icons/check_12.svg", 12, 12),
+      default: {
+        ...checkboxBase,
+        background: background(layer, "default"),
+        border: border(layer, "active"),
+      },
+      checked: {
+        ...checkboxBase,
+        background: background(layer, "hovered"),
+        border: border(layer, "active"),
+      },
+      hovered: {
+        ...checkboxBase,
+        background: background(layer, "hovered"),
+        border: border(layer, "active"),
+      },
+      hoveredAndChecked: {
+        ...checkboxBase,
+        background: background(layer, "hovered"),
+        border: border(layer, "active"),
+      },
+    },
+  }
 }

styles/src/styleTree/workspace.ts 🔗

@@ -1,338 +1,372 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
+import { toggleable } from "./toggle"
 import {
-    background,
-    border,
-    borderColor,
-    foreground,
-    svg,
-    text,
+  background,
+  border,
+  borderColor,
+  foreground,
+  svg,
+  text,
 } from "./components"
 import statusBar from "./statusBar"
 import tabBar from "./tabBar"
-
+import { interactive } from "./interactive"
+import merge from 'ts-deepmerge';
 export default function workspace(colorScheme: ColorScheme) {
-    const layer = colorScheme.lowest
-    const isLight = colorScheme.isLight
-    const itemSpacing = 8
-    const titlebarButton = {
-        cornerRadius: 6,
-        padding: {
-            top: 1,
-            bottom: 1,
-            left: 8,
-            right: 8,
-        },
-        ...text(layer, "sans", "variant", { size: "xs" }),
-        background: background(layer, "variant"),
-        border: border(layer),
-        hover: {
-            ...text(layer, "sans", "variant", "hovered", { size: "xs" }),
-            background: background(layer, "variant", "hovered"),
-            border: border(layer, "variant", "hovered"),
-        },
-        clicked: {
-            ...text(layer, "sans", "variant", "pressed", { size: "xs" }),
-            background: background(layer, "variant", "pressed"),
-            border: border(layer, "variant", "pressed"),
-        },
-        active: {
-            ...text(layer, "sans", "variant", "active", { size: "xs" }),
-            background: background(layer, "variant", "active"),
-            border: border(layer, "variant", "active"),
-        },
+  const layer = colorScheme.lowest
+  const isLight = colorScheme.isLight
+  const itemSpacing = 8
+  const titlebarButton = toggleable(interactive({
+    cornerRadius: 6,
+    padding: {
+      top: 1,
+      bottom: 1,
+      left: 8,
+      right: 8,
+    },
+    ...text(layer, "sans", "variant", { size: "xs" }),
+    background: background(layer, "variant"),
+    border: border(layer),
+  }, {
+    hover: {
+      ...text(layer, "sans", "variant", "hovered", { size: "xs" }),
+      background: background(layer, "variant", "hovered"),
+      border: border(layer, "variant", "hovered"),
+    },
+    clicked: {
+      ...text(layer, "sans", "variant", "pressed", { size: "xs" }),
+      background: background(layer, "variant", "pressed"),
+      border: border(layer, "variant", "pressed"),
     }
-    const avatarWidth = 18
-    const avatarOuterWidth = avatarWidth + 4
-    const followerAvatarWidth = 14
-    const followerAvatarOuterWidth = followerAvatarWidth + 4
+  }),
+    {
+      default: {
+        ...text(layer, "sans", "variant", "active", { size: "xs" }),
+        background: background(layer, "variant", "active"),
+        border: border(layer, "variant", "active"),
+      }
+    },
+  );
+  const avatarWidth = 18
+  const avatarOuterWidth = avatarWidth + 4
+  const followerAvatarWidth = 14
+  const followerAvatarOuterWidth = followerAvatarWidth + 4
 
-    return {
-        background: background(colorScheme.lowest),
-        blankPane: {
-            logoContainer: {
-                width: 256,
-                height: 256,
-            },
-            logo: svg(
-                withOpacity("#000000", colorScheme.isLight ? 0.6 : 0.8),
-                "icons/logo_96.svg",
-                256,
-                256
-            ),
+  return {
+    background: background(colorScheme.lowest),
+    blankPane: {
+      logoContainer: {
+        width: 256,
+        height: 256,
+      },
+      logo: svg(
+        withOpacity("#000000", colorScheme.isLight ? 0.6 : 0.8),
+        "icons/logo_96.svg",
+        256,
+        256
+      ),
 
-            logoShadow: svg(
-                withOpacity(
-                    colorScheme.isLight
-                        ? "#FFFFFF"
-                        : colorScheme.lowest.base.default.background,
-                    colorScheme.isLight ? 1 : 0.6
-                ),
-                "icons/logo_96.svg",
-                256,
-                256
-            ),
-            keyboardHints: {
-                margin: {
-                    top: 96,
-                },
-                cornerRadius: 4,
-            },
-            keyboardHint: {
-                ...text(layer, "sans", "variant", { size: "sm" }),
-                padding: {
-                    top: 3,
-                    left: 8,
-                    right: 8,
-                    bottom: 3,
-                },
-                cornerRadius: 8,
-                hover: {
-                    ...text(layer, "sans", "active", { size: "sm" }),
-                },
-            },
-            keyboardHintWidth: 320,
-        },
-        joiningProjectAvatar: {
-            cornerRadius: 40,
-            width: 80,
-        },
-        joiningProjectMessage: {
-            padding: 12,
-            ...text(layer, "sans", { size: "lg" }),
-        },
-        externalLocationMessage: {
-            background: background(colorScheme.middle, "accent"),
-            border: border(colorScheme.middle, "accent"),
-            cornerRadius: 6,
-            padding: 12,
-            margin: { bottom: 8, right: 8 },
-            ...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
-        },
-        leaderBorderOpacity: 0.7,
-        leaderBorderWidth: 2.0,
-        tabBar: tabBar(colorScheme),
-        modal: {
-            margin: {
-                bottom: 52,
-                top: 52,
-            },
-            cursor: "Arrow",
-        },
-        zoomedBackground: {
-            cursor: "Arrow",
-            background: isLight
-                ? withOpacity(background(colorScheme.lowest), 0.8)
-                : withOpacity(background(colorScheme.highest), 0.6),
-        },
-        zoomedPaneForeground: {
-            margin: 16,
-            shadow: colorScheme.modalShadow,
-            border: border(colorScheme.lowest, { overlay: true }),
-        },
-        zoomedPanelForeground: {
-            margin: 16,
-            border: border(colorScheme.lowest, { overlay: true }),
+      logoShadow: svg(
+        withOpacity(
+          colorScheme.isLight
+            ? "#FFFFFF"
+            : colorScheme.lowest.base.default.background,
+          colorScheme.isLight ? 1 : 0.6
+        ),
+        "icons/logo_96.svg",
+        256,
+        256
+      ),
+      keyboardHints: {
+        margin: {
+          top: 96,
         },
-        dock: {
-            left: {
-                border: border(layer, { right: true }),
-            },
-            bottom: {
-                border: border(layer, { top: true }),
-            },
-            right: {
-                border: border(layer, { left: true }),
-            },
-        },
-        paneDivider: {
-            color: borderColor(layer),
-            width: 1,
-        },
-        statusBar: statusBar(colorScheme),
-        titlebar: {
-            itemSpacing,
-            facePileSpacing: 2,
-            height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
-            background: background(layer),
-            border: border(layer, { bottom: true }),
-            padding: {
-                left: 80,
-                right: itemSpacing,
-            },
+        cornerRadius: 4,
+      },
+      keyboardHint:
+        interactive({
+          ...text(layer, "sans", "variant", { size: "sm" }),
+          padding: {
+            top: 3,
+            left: 8,
+            right: 8,
+            bottom: 3,
+          },
+          cornerRadius: 8
+        }, {
+          hover: {
+            ...text(layer, "sans", "active", { size: "sm" }),
+          }
+        }),
 
-            // Project
-            title: text(layer, "sans", "variant"),
-            highlight_color: text(layer, "sans", "active").color,
+      keyboardHintWidth: 320,
+    },
+    joiningProjectAvatar: {
+      cornerRadius: 40,
+      width: 80,
+    },
+    joiningProjectMessage: {
+      padding: 12,
+      ...text(layer, "sans", { size: "lg" }),
+    },
+    externalLocationMessage: {
+      background: background(colorScheme.middle, "accent"),
+      border: border(colorScheme.middle, "accent"),
+      cornerRadius: 6,
+      padding: 12,
+      margin: { bottom: 8, right: 8 },
+      ...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
+    },
+    leaderBorderOpacity: 0.7,
+    leaderBorderWidth: 2.0,
+    tabBar: tabBar(colorScheme),
+    modal: {
+      margin: {
+        bottom: 52,
+        top: 52,
+      },
+      cursor: "Arrow",
+    },
+    zoomedBackground: {
+      cursor: "Arrow",
+      background: isLight
+        ? withOpacity(background(colorScheme.lowest), 0.8)
+        : withOpacity(background(colorScheme.highest), 0.6),
+    },
+    zoomedPaneForeground: {
+      margin: 16,
+      shadow: colorScheme.modalShadow,
+      border: border(colorScheme.lowest, { overlay: true }),
+    },
+    zoomedPanelForeground: {
+      margin: 16,
+      border: border(colorScheme.lowest, { overlay: true }),
+    },
+    dock: {
+      left: {
+        border: border(layer, { right: true }),
+      },
+      bottom: {
+        border: border(layer, { top: true }),
+      },
+      right: {
+        border: border(layer, { left: true }),
+      },
+    },
+    paneDivider: {
+      color: borderColor(layer),
+      width: 1,
+    },
+    statusBar: statusBar(colorScheme),
+    titlebar: {
+      itemSpacing,
+      facePileSpacing: 2,
+      height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
+      background: background(layer),
+      border: border(layer, { bottom: true }),
+      padding: {
+        left: 80,
+        right: itemSpacing,
+      },
 
-            // Collaborators
-            leaderAvatar: {
-                width: avatarWidth,
-                outerWidth: avatarOuterWidth,
-                cornerRadius: avatarWidth / 2,
-                outerCornerRadius: avatarOuterWidth / 2,
-            },
-            followerAvatar: {
-                width: followerAvatarWidth,
-                outerWidth: followerAvatarOuterWidth,
-                cornerRadius: followerAvatarWidth / 2,
-                outerCornerRadius: followerAvatarOuterWidth / 2,
-            },
-            inactiveAvatarGrayscale: true,
-            followerAvatarOverlap: 8,
-            leaderSelection: {
-                margin: {
-                    top: 4,
-                    bottom: 4,
-                },
-                padding: {
-                    left: 2,
-                    right: 2,
-                    top: 2,
-                    bottom: 2,
-                },
-                cornerRadius: 6,
-            },
-            avatarRibbon: {
-                height: 3,
-                width: 12,
-                // TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
-            },
+      // Project
+      title: text(layer, "sans", "variant"),
+      highlight_color: text(layer, "sans", "active").color,
 
-            // Sign in buttom
-            // FlatButton, Variant
-            signInPrompt: {
-                margin: {
-                    left: itemSpacing,
-                },
-                ...titlebarButton,
-            },
+      // Collaborators
+      leaderAvatar: {
+        width: avatarWidth,
+        outerWidth: avatarOuterWidth,
+        cornerRadius: avatarWidth / 2,
+        outerCornerRadius: avatarOuterWidth / 2,
+      },
+      followerAvatar: {
+        width: followerAvatarWidth,
+        outerWidth: followerAvatarOuterWidth,
+        cornerRadius: followerAvatarWidth / 2,
+        outerCornerRadius: followerAvatarOuterWidth / 2,
+      },
+      inactiveAvatarGrayscale: true,
+      followerAvatarOverlap: 8,
+      leaderSelection: {
+        margin: {
+          top: 4,
+          bottom: 4,
+        },
+        padding: {
+          left: 2,
+          right: 2,
+          top: 2,
+          bottom: 2,
+        },
+        cornerRadius: 6,
+      },
+      avatarRibbon: {
+        height: 3,
+        width: 12,
+        // TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
+      },
 
-            // Offline Indicator
-            offlineIcon: {
-                color: foreground(layer, "variant"),
-                width: 16,
+      // Sign in buttom
+      // FlatButton, Variant
+      signInPrompt:
+        merge(titlebarButton,
+          {
+            inactive: {
+              default: {
                 margin: {
-                    left: itemSpacing,
+                  left: itemSpacing,
                 },
-                padding: {
-                    right: 4,
-                },
-            },
+              }
+            }
+          }),
 
-            // Notice that the collaboration server is out of date
-            outdatedWarning: {
-                ...text(layer, "sans", "warning", { size: "xs" }),
-                background: withOpacity(background(layer, "warning"), 0.3),
-                border: border(layer, "warning"),
-                margin: {
-                    left: itemSpacing,
-                },
-                padding: {
-                    left: 8,
-                    right: 8,
-                },
-                cornerRadius: 6,
-            },
-            callControl: {
-                cornerRadius: 6,
-                color: foreground(layer, "variant"),
-                iconWidth: 12,
-                buttonWidth: 20,
-                hover: {
-                    background: background(layer, "variant", "hovered"),
-                    color: foreground(layer, "variant", "hovered"),
-                },
-            },
-            toggleContactsButton: {
-                margin: { left: itemSpacing },
-                cornerRadius: 6,
-                color: foreground(layer, "variant"),
-                iconWidth: 14,
-                buttonWidth: 20,
-                active: {
-                    background: background(layer, "variant", "active"),
-                    color: foreground(layer, "variant", "active"),
-                },
-                clicked: {
-                    background: background(layer, "variant", "pressed"),
-                    color: foreground(layer, "variant", "pressed"),
-                },
-                hover: {
-                    background: background(layer, "variant", "hovered"),
-                    color: foreground(layer, "variant", "hovered"),
-                },
-            },
-            userMenuButton: {
-                buttonWidth: 20,
-                iconWidth: 12,
-                ...titlebarButton,
-            },
-            toggleContactsBadge: {
-                cornerRadius: 3,
-                padding: 2,
-                margin: { top: 3, left: 3 },
-                border: border(layer),
-                background: foreground(layer, "accent"),
-            },
-            shareButton: {
-                ...titlebarButton,
-            },
+
+      // Offline Indicator
+      offlineIcon: {
+        color: foreground(layer, "variant"),
+        width: 16,
+        margin: {
+          left: itemSpacing,
+        },
+        padding: {
+          right: 4,
         },
+      },
 
-        toolbar: {
-            height: 34,
-            background: background(colorScheme.highest),
-            border: border(colorScheme.highest, { bottom: true }),
-            itemSpacing: 8,
-            navButton: {
-                color: foreground(colorScheme.highest, "on"),
-                iconWidth: 12,
-                buttonWidth: 24,
-                cornerRadius: 6,
-                hover: {
-                    color: foreground(colorScheme.highest, "on", "hovered"),
-                    background: background(
-                        colorScheme.highest,
-                        "on",
-                        "hovered"
-                    ),
-                },
-                disabled: {
-                    color: foreground(colorScheme.highest, "on", "disabled"),
-                },
-            },
-            padding: { left: 8, right: 8, top: 4, bottom: 4 },
+      // Notice that the collaboration server is out of date
+      outdatedWarning: {
+        ...text(layer, "sans", "warning", { size: "xs" }),
+        background: withOpacity(background(layer, "warning"), 0.3),
+        border: border(layer, "warning"),
+        margin: {
+          left: itemSpacing,
+        },
+        padding: {
+          left: 8,
+          right: 8,
         },
-        breadcrumbHeight: 24,
-        breadcrumbs: {
-            ...text(colorScheme.highest, "sans", "variant"),
-            cornerRadius: 6,
-            padding: {
-                left: 6,
-                right: 6,
-            },
-            hover: {
-                color: foreground(colorScheme.highest, "on", "hovered"),
-                background: background(colorScheme.highest, "on", "hovered"),
-            },
+        cornerRadius: 6,
+      },
+      callControl: interactive({
+        cornerRadius: 6,
+        color: foreground(layer, "variant"),
+        iconWidth: 12,
+        buttonWidth: 20,
+      }, {
+        hover: {
+          background: background(layer, "variant", "hovered"),
+          color: foreground(layer, "variant", "hovered"),
         },
-        disconnectedOverlay: {
-            ...text(layer, "sans"),
-            background: withOpacity(background(layer), 0.8),
+      }),
+      toggleContactsButton: toggleable(interactive({
+        margin: { left: itemSpacing },
+        cornerRadius: 6,
+        color: foreground(layer, "variant"),
+        iconWidth: 14,
+        buttonWidth: 20,
+      },
+        {
+          clicked: {
+            background: background(layer, "variant", "pressed"),
+            color: foreground(layer, "variant", "pressed"),
+          },
+          hover: {
+            background: background(layer, "variant", "hovered"),
+            color: foreground(layer, "variant", "hovered"),
+          }
+        }),
+        {
+          default: {
+            background: background(layer, "variant", "active"),
+            color: foreground(layer, "variant", "active")
+          }
         },
-        notification: {
-            margin: { top: 10 },
-            background: background(colorScheme.middle),
-            cornerRadius: 6,
-            padding: 12,
-            border: border(colorScheme.middle),
-            shadow: colorScheme.popoverShadow,
+      ),
+      userMenuButton: merge(titlebarButton, {
+        inactive: {
+          default: {
+            buttonWidth: 20,
+            iconWidth: 12
+          }
+        }, active: { // posiewic: these properties are not currently set on main
+          default: {
+            iconWidth: 12,
+            button_width: 20,
+          }
+        }
+      }),
+
+
+      toggleContactsBadge: {
+        cornerRadius: 3,
+        padding: 2,
+        margin: { top: 3, left: 3 },
+        border: border(layer),
+        background: foreground(layer, "accent"),
+      },
+      shareButton: {
+        ...titlebarButton,
+      },
+    },
+
+    toolbar: {
+      height: 34,
+      background: background(colorScheme.highest),
+      border: border(colorScheme.highest, { bottom: true }),
+      itemSpacing: 8,
+      navButton: interactive(
+        {
+          color: foreground(colorScheme.highest, "on"),
+          iconWidth: 12,
+          buttonWidth: 24,
+          cornerRadius: 6,
+        }, {
+        hover: {
+          color: foreground(colorScheme.highest, "on", "hovered"),
+          background: background(
+            colorScheme.highest,
+            "on",
+            "hovered"
+          ),
         },
-        notifications: {
-            width: 400,
-            margin: { right: 10, bottom: 10 },
+        disabled: {
+          color: foreground(colorScheme.highest, "on", "disabled"),
         },
-        dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
-    }
+      }),
+      padding: { left: 8, right: 8, top: 4, bottom: 4 },
+    },
+    breadcrumbHeight: 24,
+    breadcrumbs: interactive({
+      ...text(colorScheme.highest, "sans", "variant"),
+      cornerRadius: 6,
+      padding: {
+        left: 6,
+        right: 6,
+      }
+    }, {
+      hover: {
+        color: foreground(colorScheme.highest, "on", "hovered"),
+        background: background(colorScheme.highest, "on", "hovered"),
+      },
+    }),
+    disconnectedOverlay: {
+      ...text(layer, "sans"),
+      background: withOpacity(background(layer), 0.8),
+    },
+    notification: {
+      margin: { top: 10 },
+      background: background(colorScheme.middle),
+      cornerRadius: 6,
+      padding: 12,
+      border: border(colorScheme.middle),
+      shadow: colorScheme.popoverShadow,
+    },
+    notifications: {
+      width: 400,
+      margin: { right: 10, bottom: 10 },
+    },
+    dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
+  }
 }