Start loading new theme JSON format instead of TOML

Nathan Sobo and Nathan Sobo created

Replaced remaining extends with javascript object extension.
Moved tokens/core.ts to tokens.ts and massaged the types to make it more
obvious when types don't match up.

Co-authored-by: Nathan Sobo <nathan@zed.dev>

Change summary

crates/theme/src/resolution.rs      |  497 ------------
crates/theme/src/theme.rs           |    3 
crates/theme/src/theme_registry.rs  |  234 -----
crates/zed/assets/themes/_base.toml |  411 ----------
crates/zed/assets/themes/black.toml |   67 -
crates/zed/assets/themes/dark.json  | 1245 ++++++++++++++++++++++++++++++
crates/zed/assets/themes/dark.toml  |   67 -
crates/zed/assets/themes/light.json | 1245 ++++++++++++++++++++++++++++++
crates/zed/assets/themes/light.toml |   67 -
crates/zed/src/zed.rs               |    3 
styles/buildThemes.ts               |   14 
styles/styleTree/app.ts             |  106 -
styles/styleTree/components.ts      |   14 
styles/styleTree/contactsPanel.ts   |   61 +
styles/styleTree/editor.ts          |  245 +++---
styles/styleTree/projectPanel.ts    |    6 
styles/styleTree/search.ts          |   44 
styles/styleTree/workspace.ts       |    5 
styles/themes/dark.ts               |  462 ++++++-----
styles/themes/light.ts              |  300 ++++---
styles/themes/theme.ts              |   37 
styles/tokens.ts                    |  102 ++
styles/tokens/core.ts               |   58 -
23 files changed, 3,284 insertions(+), 2,009 deletions(-)

Detailed changes

crates/theme/src/resolution.rs 🔗

@@ -1,497 +0,0 @@
-use anyhow::{anyhow, Result};
-use indexmap::IndexMap;
-use serde_json::Value;
-use std::{
-    cell::RefCell,
-    mem,
-    rc::{Rc, Weak},
-};
-
-pub fn resolve_references(value: Value) -> Result<Value> {
-    let tree = Tree::from_json(value)?;
-    tree.resolve()?;
-    tree.to_json()
-}
-
-#[derive(Clone)]
-enum Node {
-    Reference {
-        path: String,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Object {
-        base: Option<String>,
-        children: IndexMap<String, Tree>,
-        resolved: bool,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Array {
-        children: Vec<Tree>,
-        resolved: bool,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    String {
-        value: String,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Number {
-        value: serde_json::Number,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Bool {
-        value: bool,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Null {
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-}
-
-#[derive(Clone)]
-struct Tree(Rc<RefCell<Node>>);
-
-impl Tree {
-    pub fn new(node: Node) -> Self {
-        Self(Rc::new(RefCell::new(node)))
-    }
-
-    fn from_json(value: Value) -> Result<Self> {
-        match value {
-            Value::String(value) => {
-                if let Some(path) = value.strip_prefix("$") {
-                    Ok(Self::new(Node::Reference {
-                        path: path.to_string(),
-                        parent: None,
-                    }))
-                } else {
-                    Ok(Self::new(Node::String {
-                        value,
-                        parent: None,
-                    }))
-                }
-            }
-            Value::Number(value) => Ok(Self::new(Node::Number {
-                value,
-                parent: None,
-            })),
-            Value::Bool(value) => Ok(Self::new(Node::Bool {
-                value,
-                parent: None,
-            })),
-            Value::Null => Ok(Self::new(Node::Null { parent: None })),
-            Value::Object(object) => {
-                let tree = Self::new(Node::Object {
-                    base: Default::default(),
-                    children: Default::default(),
-                    resolved: false,
-                    parent: None,
-                });
-                let mut children = IndexMap::new();
-                let mut resolved = true;
-                let mut base = None;
-                for (key, value) in object.into_iter() {
-                    let value = if key == "extends" {
-                        if value.is_string() {
-                            if let Value::String(value) = value {
-                                base = value.strip_prefix("$").map(str::to_string);
-                                resolved = false;
-                                Self::new(Node::String {
-                                    value,
-                                    parent: None,
-                                })
-                            } else {
-                                unreachable!()
-                            }
-                        } else {
-                            Tree::from_json(value)?
-                        }
-                    } else {
-                        Tree::from_json(value)?
-                    };
-                    value
-                        .0
-                        .borrow_mut()
-                        .set_parent(Some(Rc::downgrade(&tree.0)));
-                    resolved &= value.is_resolved();
-                    children.insert(key.clone(), value);
-                }
-
-                *tree.0.borrow_mut() = Node::Object {
-                    base,
-                    children,
-                    resolved,
-                    parent: None,
-                };
-                Ok(tree)
-            }
-            Value::Array(elements) => {
-                let tree = Self::new(Node::Array {
-                    children: Default::default(),
-                    resolved: false,
-                    parent: None,
-                });
-
-                let mut children = Vec::new();
-                let mut resolved = true;
-                for element in elements {
-                    let child = Tree::from_json(element)?;
-                    child
-                        .0
-                        .borrow_mut()
-                        .set_parent(Some(Rc::downgrade(&tree.0)));
-                    resolved &= child.is_resolved();
-                    children.push(child);
-                }
-
-                *tree.0.borrow_mut() = Node::Array {
-                    children,
-                    resolved,
-                    parent: None,
-                };
-                Ok(tree)
-            }
-        }
-    }
-
-    fn to_json(&self) -> Result<Value> {
-        match &*self.0.borrow() {
-            Node::Reference { .. } => Err(anyhow!("unresolved tree")),
-            Node::String { value, .. } => Ok(Value::String(value.clone())),
-            Node::Number { value, .. } => Ok(Value::Number(value.clone())),
-            Node::Bool { value, .. } => Ok(Value::Bool(*value)),
-            Node::Null { .. } => Ok(Value::Null),
-            Node::Object { children, .. } => {
-                let mut json_children = serde_json::Map::new();
-                for (key, value) in children {
-                    json_children.insert(key.clone(), value.to_json()?);
-                }
-                Ok(Value::Object(json_children))
-            }
-            Node::Array { children, .. } => {
-                let mut json_children = Vec::new();
-                for child in children {
-                    json_children.push(child.to_json()?);
-                }
-                Ok(Value::Array(json_children))
-            }
-        }
-    }
-
-    fn parent(&self) -> Option<Tree> {
-        match &*self.0.borrow() {
-            Node::Reference { parent, .. }
-            | Node::Object { parent, .. }
-            | Node::Array { parent, .. }
-            | Node::String { parent, .. }
-            | Node::Number { parent, .. }
-            | Node::Bool { parent, .. }
-            | Node::Null { parent } => parent.as_ref().and_then(|p| p.upgrade()).map(Tree),
-        }
-    }
-
-    fn get(&self, path: &str) -> Result<Option<Tree>> {
-        let mut tree = self.clone();
-        for component in path.split('.') {
-            let node = tree.0.borrow();
-            match &*node {
-                Node::Object { children, .. } => {
-                    if let Some(subtree) = children.get(component).cloned() {
-                        drop(node);
-                        tree = subtree;
-                    } else {
-                        return Err(anyhow!(
-                            "key \"{}\" does not exist in path \"{}\"",
-                            component,
-                            path
-                        ));
-                    }
-                }
-                Node::Reference { .. } => return Ok(None),
-                Node::Array { .. }
-                | Node::String { .. }
-                | Node::Number { .. }
-                | Node::Bool { .. }
-                | Node::Null { .. } => {
-                    return Err(anyhow!(
-                        "key \"{}\" in path \"{}\" is not an object",
-                        component,
-                        path
-                    ))
-                }
-            }
-        }
-
-        Ok(Some(tree))
-    }
-
-    fn is_resolved(&self) -> bool {
-        match &*self.0.borrow() {
-            Node::Reference { .. } => false,
-            Node::Object { resolved, .. } | Node::Array { resolved, .. } => *resolved,
-            Node::String { .. } | Node::Number { .. } | Node::Bool { .. } | Node::Null { .. } => {
-                true
-            }
-        }
-    }
-
-    fn update_resolved(&self) {
-        match &mut *self.0.borrow_mut() {
-            Node::Object {
-                resolved,
-                base,
-                children,
-                ..
-            } => {
-                *resolved = base.is_none() && children.values().all(|c| c.is_resolved());
-            }
-            Node::Array {
-                resolved, children, ..
-            } => {
-                *resolved = children.iter().all(|c| c.is_resolved());
-            }
-            _ => {}
-        }
-    }
-
-    pub fn resolve(&self) -> Result<()> {
-        let mut unresolved = vec![self.clone()];
-        let mut made_progress = true;
-
-        while made_progress && !unresolved.is_empty() {
-            made_progress = false;
-            for mut tree in mem::take(&mut unresolved) {
-                made_progress |= tree.resolve_subtree(self, &mut unresolved)?;
-                if tree.is_resolved() {
-                    while let Some(parent) = tree.parent() {
-                        parent.update_resolved();
-                        if !parent.is_resolved() {
-                            break;
-                        }
-                        tree = parent;
-                    }
-                }
-            }
-        }
-
-        if unresolved.is_empty() {
-            Ok(())
-        } else {
-            Err(anyhow!("tree contains cycles"))
-        }
-    }
-
-    fn resolve_subtree(&self, root: &Tree, unresolved: &mut Vec<Tree>) -> Result<bool> {
-        let node = self.0.borrow();
-        match &*node {
-            Node::Reference { path, parent } => {
-                if let Some(subtree) = root.get(&path)? {
-                    if subtree.is_resolved() {
-                        let parent = parent.clone();
-                        drop(node);
-                        let mut new_node = subtree.0.borrow().clone();
-                        new_node.set_parent(parent);
-                        *self.0.borrow_mut() = new_node;
-                        Ok(true)
-                    } else {
-                        unresolved.push(self.clone());
-                        Ok(false)
-                    }
-                } else {
-                    unresolved.push(self.clone());
-                    Ok(false)
-                }
-            }
-            Node::Object {
-                base,
-                children,
-                resolved,
-                ..
-            } => {
-                if *resolved {
-                    Ok(false)
-                } else {
-                    let mut made_progress = false;
-                    let mut children_resolved = true;
-                    for child in children.values() {
-                        made_progress |= child.resolve_subtree(root, unresolved)?;
-                        children_resolved &= child.is_resolved();
-                    }
-
-                    if children_resolved {
-                        let mut has_base = false;
-                        let mut resolved_base = None;
-                        if let Some(base) = base {
-                            has_base = true;
-                            if let Some(base) = root.get(base)? {
-                                if base.is_resolved() {
-                                    resolved_base = Some(base);
-                                }
-                            }
-                        }
-
-                        drop(node);
-
-                        if let Some(base) = resolved_base.as_ref() {
-                            self.extend_from(&base);
-                            made_progress = true;
-                        }
-
-                        if let Node::Object { resolved, base, .. } = &mut *self.0.borrow_mut() {
-                            if has_base {
-                                if resolved_base.is_some() {
-                                    base.take();
-                                    *resolved = true;
-                                } else {
-                                    unresolved.push(self.clone());
-                                }
-                            } else {
-                                *resolved = true;
-                            }
-                        }
-                    } else if base.is_some() {
-                        unresolved.push(self.clone());
-                    }
-
-                    Ok(made_progress)
-                }
-            }
-            Node::Array {
-                children, resolved, ..
-            } => {
-                if *resolved {
-                    Ok(false)
-                } else {
-                    let mut made_progress = false;
-                    let mut children_resolved = true;
-                    for child in children.iter() {
-                        made_progress |= child.resolve_subtree(root, unresolved)?;
-                        children_resolved &= child.is_resolved();
-                    }
-
-                    if children_resolved {
-                        drop(node);
-
-                        if let Node::Array { resolved, .. } = &mut *self.0.borrow_mut() {
-                            *resolved = true;
-                        }
-                    }
-
-                    Ok(made_progress)
-                }
-            }
-            Node::String { .. } | Node::Number { .. } | Node::Bool { .. } | Node::Null { .. } => {
-                Ok(false)
-            }
-        }
-    }
-
-    fn extend_from(&self, base: &Tree) {
-        if Rc::ptr_eq(&self.0, &base.0) {
-            return;
-        }
-
-        if let (
-            Node::Object { children, .. },
-            Node::Object {
-                children: base_children,
-                ..
-            },
-        ) = (&mut *self.0.borrow_mut(), &*base.0.borrow())
-        {
-            for (key, base_value) in base_children {
-                if let Some(value) = children.get(key) {
-                    value.extend_from(base_value);
-                } else {
-                    let base_value = base_value.clone();
-                    base_value
-                        .0
-                        .borrow_mut()
-                        .set_parent(Some(Rc::downgrade(&self.0)));
-                    children.insert(key.clone(), base_value);
-                }
-            }
-        }
-    }
-}
-
-impl Node {
-    fn set_parent(&mut self, new_parent: Option<Weak<RefCell<Node>>>) {
-        match self {
-            Node::Reference { parent, .. }
-            | Node::Object { parent, .. }
-            | Node::Array { parent, .. }
-            | Node::String { parent, .. }
-            | Node::Number { parent, .. }
-            | Node::Bool { parent, .. }
-            | Node::Null { parent } => *parent = new_parent,
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-
-    #[test]
-    fn test_references() {
-        let json = serde_json::json!({
-            "a": {
-                "extends": "$g",
-                "x": "$b.d"
-            },
-            "b": {
-                "c": "$a",
-                "d": "$e.f"
-            },
-            "e": {
-                "extends": "$a",
-                "f": "1"
-            },
-            "g": {
-                "h": 2
-            }
-        });
-
-        assert_eq!(
-            resolve_references(json).unwrap(),
-            serde_json::json!({
-                "a": {
-                    "extends": "$g",
-                    "x": "1",
-                    "h": 2
-                },
-                "b": {
-                    "c": {
-                        "extends": "$g",
-                        "x": "1",
-                        "h": 2
-                    },
-                    "d": "1"
-                },
-                "e": {
-                    "extends": "$a",
-                    "f": "1",
-                    "x": "1",
-                    "h": 2
-                },
-                "g": {
-                    "h": 2
-                }
-            })
-        )
-    }
-
-    #[test]
-    fn test_cycles() {
-        let json = serde_json::json!({
-            "a": {
-                "b": "$c.d"
-            },
-            "c": {
-                "d": "$a.b",
-            },
-        });
-
-        assert!(resolve_references(json).is_err());
-    }
-}

crates/theme/src/theme.rs 🔗

@@ -1,4 +1,3 @@
-mod resolution;
 mod theme_registry;
 
 use gpui::{
@@ -12,7 +11,7 @@ use std::{collections::HashMap, sync::Arc};
 
 pub use theme_registry::*;
 
-pub const DEFAULT_THEME_NAME: &'static str = "black";
+pub const DEFAULT_THEME_NAME: &'static str = "dark";
 
 #[derive(Deserialize, Default)]
 pub struct Theme {

crates/theme/src/theme_registry.rs 🔗

@@ -1,8 +1,8 @@
-use crate::{resolution::resolve_references, Theme};
+use crate::Theme;
 use anyhow::{Context, Result};
 use gpui::{fonts, AssetSource, FontCache};
 use parking_lot::Mutex;
-use serde_json::{Map, Value};
+use serde_json::Value;
 use std::{collections::HashMap, sync::Arc};
 
 pub struct ThemeRegistry {
@@ -25,12 +25,8 @@ impl ThemeRegistry {
     pub fn list(&self) -> impl Iterator<Item = String> {
         self.assets.list("themes/").into_iter().filter_map(|path| {
             let filename = path.strip_prefix("themes/")?;
-            let theme_name = filename.strip_suffix(".toml")?;
-            if theme_name.starts_with('_') {
-                None
-            } else {
-                Some(theme_name.to_string())
-            }
+            let theme_name = filename.strip_suffix(".json")?;
+            Some(theme_name.to_string())
         })
     }
 
@@ -44,9 +40,14 @@ impl ThemeRegistry {
             return Ok(theme.clone());
         }
 
-        let theme_data = self.load(name, true)?;
+        let asset_path = format!("themes/{}.json", name);
+        let theme_json = self
+            .assets
+            .load(&asset_path)
+            .with_context(|| format!("failed to load theme file {}", asset_path))?;
+
         let mut theme: Theme = fonts::with_font_cache(self.font_cache.clone(), || {
-            serde_path_to_error::deserialize(theme_data.as_ref())
+            serde_path_to_error::deserialize(&mut serde_json::Deserializer::from_slice(&theme_json))
         })?;
 
         theme.name = name.into();
@@ -54,217 +55,4 @@ impl ThemeRegistry {
         self.themes.lock().insert(name.to_string(), theme.clone());
         Ok(theme)
     }
-
-    fn load(&self, name: &str, evaluate_references: bool) -> Result<Arc<Value>> {
-        if let Some(data) = self.theme_data.lock().get(name) {
-            return Ok(data.clone());
-        }
-
-        let asset_path = format!("themes/{}.toml", name);
-        let source_code = self
-            .assets
-            .load(&asset_path)
-            .with_context(|| format!("failed to load theme file {}", asset_path))?;
-
-        let mut theme_data: Map<String, Value> = toml::from_slice(source_code.as_ref())
-            .with_context(|| format!("failed to parse {}.toml", name))?;
-
-        // If this theme extends another base theme, deeply merge it into the base theme's data
-        if let Some(base_name) = theme_data
-            .get("extends")
-            .and_then(|name| name.as_str())
-            .map(str::to_string)
-        {
-            let base_theme_data = self
-                .load(&base_name, false)
-                .with_context(|| format!("failed to load base theme {}", base_name))?
-                .as_ref()
-                .clone();
-            if let Value::Object(mut base_theme_object) = base_theme_data {
-                deep_merge_json(&mut base_theme_object, theme_data);
-                theme_data = base_theme_object;
-            }
-        }
-
-        let mut theme_data = Value::Object(theme_data);
-
-        // Find all of the key path references in the object, and then sort them according
-        // to their dependencies.
-        if evaluate_references {
-            theme_data = resolve_references(theme_data)?;
-        }
-
-        let result = Arc::new(theme_data);
-        self.theme_data
-            .lock()
-            .insert(name.to_string(), result.clone());
-
-        Ok(result)
-    }
-}
-
-fn deep_merge_json(base: &mut Map<String, Value>, extension: Map<String, Value>) {
-    for (key, extension_value) in extension {
-        if let Value::Object(extension_object) = extension_value {
-            if let Some(base_object) = base.get_mut(&key).and_then(|value| value.as_object_mut()) {
-                deep_merge_json(base_object, extension_object);
-            } else {
-                base.insert(key, Value::Object(extension_object));
-            }
-        } else {
-            base.insert(key, extension_value);
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use anyhow::anyhow;
-    use gpui::MutableAppContext;
-
-    #[gpui::test]
-    fn test_theme_extension(cx: &mut MutableAppContext) {
-        let assets = TestAssets(&[
-            (
-                "themes/_base.toml",
-                r##"
-                [ui.active_tab]
-                extends = "$ui.tab"
-                border.color = "#666666"
-                text = "$text_colors.bright"
-
-                [ui.tab]
-                extends = "$ui.element"
-                text = "$text_colors.dull"
-
-                [ui.element]
-                background = "#111111"
-                border = {width = 2.0, color = "#00000000"}
-
-                [editor]
-                background = "#222222"
-                default_text = "$text_colors.regular"
-                "##,
-            ),
-            (
-                "themes/light.toml",
-                r##"
-                extends = "_base"
-
-                [text_colors]
-                bright = "#ffffff"
-                regular = "#eeeeee"
-                dull = "#dddddd"
-
-                [editor]
-                background = "#232323"
-                "##,
-            ),
-        ]);
-
-        let registry = ThemeRegistry::new(assets, cx.font_cache().clone());
-        let theme_data = registry.load("light", true).unwrap();
-
-        assert_eq!(
-            theme_data.as_ref(),
-            &serde_json::json!({
-              "ui": {
-                "active_tab": {
-                  "background": "#111111",
-                  "border": {
-                    "width": 2.0,
-                    "color": "#666666"
-                  },
-                  "extends": "$ui.tab",
-                  "text": "#ffffff"
-                },
-                "tab": {
-                  "background": "#111111",
-                  "border": {
-                    "width": 2.0,
-                    "color": "#00000000"
-                  },
-                  "extends": "$ui.element",
-                  "text": "#dddddd"
-                },
-                "element": {
-                  "background": "#111111",
-                  "border": {
-                    "width": 2.0,
-                    "color": "#00000000"
-                  }
-                }
-              },
-              "editor": {
-                "background": "#232323",
-                "default_text": "#eeeeee"
-              },
-              "extends": "_base",
-              "text_colors": {
-                "bright": "#ffffff",
-                "regular": "#eeeeee",
-                "dull": "#dddddd"
-              }
-            })
-        );
-    }
-
-    #[gpui::test]
-    fn test_nested_extension(cx: &mut MutableAppContext) {
-        let assets = TestAssets(&[(
-            "themes/theme.toml",
-            r##"
-                [a]
-                text = { extends = "$text.0" }
-
-                [b]
-                extends = "$a"
-                text = { extends = "$text.1" }
-
-                [text]
-                0 = { color = "red" }
-                1 = { color = "blue" }
-            "##,
-        )]);
-
-        let registry = ThemeRegistry::new(assets, cx.font_cache().clone());
-        let theme_data = registry.load("theme", true).unwrap();
-        assert_eq!(
-            theme_data
-                .get("b")
-                .unwrap()
-                .get("text")
-                .unwrap()
-                .get("color")
-                .unwrap(),
-            "blue"
-        );
-    }
-
-    struct TestAssets(&'static [(&'static str, &'static str)]);
-
-    impl AssetSource for TestAssets {
-        fn load(&self, path: &str) -> Result<std::borrow::Cow<[u8]>> {
-            if let Some(row) = self.0.iter().find(|e| e.0 == path) {
-                Ok(row.1.as_bytes().into())
-            } else {
-                Err(anyhow!("no such path {}", path))
-            }
-        }
-
-        fn list(&self, prefix: &str) -> Vec<std::borrow::Cow<'static, str>> {
-            self.0
-                .iter()
-                .copied()
-                .filter_map(|(path, _)| {
-                    if path.starts_with(prefix) {
-                        Some(path.into())
-                    } else {
-                        None
-                    }
-                })
-                .collect()
-        }
-    }
 }

crates/zed/assets/themes/_base.toml 🔗

@@ -1,411 +0,0 @@
-[text]
-base = { family = "Zed Sans", size = 14 }
-
-[workspace]
-background = "$surface.0"
-pane_divider = { width = 1, color = "$border.0" }
-leader_border_opacity = 0.7
-leader_border_width = 2.0
-
-[workspace.titlebar]
-height = 32
-border = { width = 1, bottom = true, color = "$border.0" }
-title = "$text.0"
-avatar_width = 18
-avatar = { corner_radius = 10, border = { width = 1, color = "#00000088" } }
-avatar_ribbon = { background = "#ff0000", height = 3, width = 12 }
-outdated_warning = { extends = "$text.2", size = 13 }
-share_icon_color = "$text.2.color"
-share_icon_active_color = "$text.0.color"
-
-[workspace.titlebar.sign_in_prompt]
-extends = "$text.2"
-size = 13
-underline = true
-padding = { right = 8 }
-
-[workspace.titlebar.hovered_sign_in_prompt]
-extends = "$workspace.titlebar.sign_in_prompt"
-color = "$text.1.color"
-
-[workspace.titlebar.offline_icon]
-padding = { right = 4 }
-width = 16
-color = "$text.2.color"
-
-[workspace.tab]
-height = 34
-text = "$text.2"
-padding = { left = 12, right = 12 }
-icon_width = 8
-spacing = 10
-icon_close = "$text.2.color"
-icon_close_active = "$text.0.color"
-icon_dirty = "$status.info"
-icon_conflict = "$status.warn"
-border = { left = true, bottom = true, width = 1, color = "$border.0", overlay = true }
-
-[workspace.active_tab]
-extends = "$workspace.tab"
-border.bottom = false
-background = "$surface.1"
-text = "$text.0"
-
-[workspace.sidebar]
-width = 30
-border = { right = true, width = 1, color = "$border.0" }
-
-[workspace.sidebar.resize_handle]
-padding = { left = 1 }
-background = "$border.0"
-
-[workspace.sidebar.item]
-icon_color = "$text.2.color"
-icon_size = 18
-height = "$workspace.tab.height"
-
-[workspace.sidebar.active_item]
-extends = "$workspace.sidebar.item"
-icon_color = "$text.0.color"
-
-[workspace.left_sidebar]
-extends = "$workspace.sidebar"
-border = { width = 1, color = "$border.0", right = true }
-
-[workspace.right_sidebar]
-extends = "$workspace.sidebar"
-border = { width = 1, color = "$border.0", left = true }
-
-[workspace.status_bar]
-padding = { left = 6, right = 6 }
-height = 24
-item_spacing = 8
-cursor_position = "$text.2"
-diagnostic_message = "$text.2"
-lsp_message = "$text.2"
-
-[workspace.toolbar]
-background = "$surface.1"
-border = { color = "$border.0", width = 1, left = false, right = false, bottom = true, top = false }
-height = 34
-item_spacing = 8
-padding = { left = 16, right = 8, top = 4, bottom = 4 }
-
-[breadcrumbs]
-extends = "$text.1"
-padding = { left = 6 }
-
-[panel]
-padding = { top = 12, left = 12, bottom = 12, right = 12 }
-
-[chat_panel]
-extends = "$panel"
-channel_name = { extends = "$text.0", weight = "bold" }
-channel_name_hash = { text = "$text.2", padding.right = 8 }
-
-[chat_panel.message]
-body = "$text.1"
-sender = { extends = "$text.0", weight = "bold", margin.right = 8 }
-timestamp = "$text.2"
-padding.bottom = 6
-
-[chat_panel.pending_message]
-extends = "$chat_panel.message"
-body = { color = "$text.3.color" }
-sender = { color = "$text.3.color" }
-timestamp = { color = "$text.3.color" }
-
-[chat_panel.channel_select.item]
-padding = 4
-name = "$text.1"
-hash = { extends = "$text.2", margin.right = 8 }
-
-[chat_panel.channel_select.hovered_item]
-extends = "$chat_panel.channel_select.item"
-background = "$state.hover"
-corner_radius = 6
-
-[chat_panel.channel_select.active_item]
-extends = "$chat_panel.channel_select.item"
-name = "$text.0"
-
-[chat_panel.channel_select.hovered_active_item]
-extends = "$chat_panel.channel_select.hovered_item"
-name = "$text.0"
-
-[chat_panel.channel_select.header]
-extends = "$chat_panel.channel_select.active_item"
-padding.bottom = 4
-padding.left = 0
-
-[chat_panel.channel_select.menu]
-padding = 4
-corner_radius = 6
-border = { color = "$border.0", width = 1 }
-background = "$surface.0"
-shadow = { offset = [0, 2], blur = 16, color = "$shadow.0" }
-
-[chat_panel.input_editor]
-background = "$surface.1"
-corner_radius = 6
-padding = { left = 8, right = 8, top = 7, bottom = 7 }
-text = "$text.0"
-placeholder_text = "$text.2"
-selection = "$selection.host"
-border = { width = 1, color = "$border.0" }
-
-[chat_panel.sign_in_prompt]
-extends = "$text.0"
-underline = true
-
-[chat_panel.hovered_sign_in_prompt]
-extends = "$chat_panel.sign_in_prompt"
-color = "$text.1.color"
-
-[contacts_panel]
-extends = "$panel"
-host_row_height = 28
-host_avatar = { corner_radius = 10, width = 18 }
-host_username = { extends = "$text.0", padding.left = 8 }
-tree_branch_width = 1
-tree_branch_color = "$surface.2"
-
-[contacts_panel.project]
-height = 24
-padding = { left = 8 }
-guest_avatar = { corner_radius = 8, width = 14 }
-guest_avatar_spacing = 4
-
-[contacts_panel.project.name]
-extends = "$text.1"
-margin = { right = 6 }
-
-[contacts_panel.unshared_project]
-extends = "$contacts_panel.project"
-
-[contacts_panel.hovered_unshared_project]
-extends = "$contacts_panel.unshared_project"
-background = "$state.hover"
-corner_radius = 6
-
-[contacts_panel.shared_project]
-extends = "$contacts_panel.project"
-name.color = "$text.0.color"
-
-[contacts_panel.hovered_shared_project]
-extends = "$contacts_panel.shared_project"
-background = "$state.hover"
-corner_radius = 6
-
-[project_panel]
-extends = "$panel"
-padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
-
-[project_panel.entry]
-text = "$text.1"
-height = 22
-icon_color = "$text.3.color"
-icon_size = 8
-icon_spacing = 8
-
-[project_panel.hovered_entry]
-extends = "$project_panel.entry"
-background = "$state.hover"
-
-[project_panel.selected_entry]
-extends = "$project_panel.entry"
-text = { extends = "$text.0" }
-
-[project_panel.hovered_selected_entry]
-extends = "$project_panel.hovered_entry"
-text = { extends = "$text.0" }
-
-[selector]
-background = "$surface.0"
-padding = 8
-margin = { top = 52, bottom = 52 }
-corner_radius = 6
-shadow = { offset = [0, 2], blur = 16, color = "$shadow.0" }
-border = { width = 1, color = "$border.0" }
-
-[selector.input_editor]
-background = "$surface.1"
-corner_radius = 6
-padding = { left = 16, right = 16, top = 7, bottom = 7 }
-text = "$text.0"
-placeholder_text = "$text.2"
-selection = "$selection.host"
-border = { width = 1, color = "$border.0" }
-
-[selector.empty]
-text = "$text.2"
-padding = { left = 16, right = 16, top = 8, bottom = 4 }
-
-[selector.item]
-text = "$text.1"
-highlight_text = { extends = "$text.base", color = "$editor.syntax.keyword.color", weight = "$editor.syntax.keyword.weight" }
-padding = { left = 16, right = 16, top = 4, bottom = 4 }
-corner_radius = 6
-
-[selector.active_item]
-extends = "$selector.item"
-background = "$state.hover"
-text = "$text.0"
-
-[editor]
-text_color = "$text.1.color"
-background = "$surface.1"
-gutter_background = "$surface.1"
-gutter_padding_factor = 2.5
-active_line_background = "$state.active_line"
-highlighted_line_background = "$state.highlighted_line"
-rename_fade = 0.6
-unnecessary_code_fade = 0.5
-document_highlight_read_background = "#99999920"
-document_highlight_write_background = "#99999916"
-diff_background_deleted = "$state.deleted_line"
-diff_background_inserted = "$state.inserted_line"
-line_number = "$text.2.color"
-line_number_active = "$text.0.color"
-selection = "$selection.host"
-guest_selections = "$selection.guests"
-error_color = "$status.bad"
-code_actions_indicator = "$text.3.color"
-
-[editor.diagnostic_path_header]
-background = "$state.active_line"
-filename = { extends = "$text.0", size = 14 }
-path = { extends = "$text.2", size = 14, margin.left = 12 }
-text_scale_factor = 0.857
-
-[editor.diagnostic_header]
-background = "$editor.background"
-border = { width = 1, top = true, bottom = true, color = "$border.1" }
-code = { extends = "$text.2", size = 14, margin.left = 10 }
-icon_width_factor = 1.5
-text_scale_factor = 0.857
-
-[editor.diagnostic_header.message]
-text = { extends = "$text.1", size = 14 }
-highlight_text = { extends = "$text.0", size = 14, weight = "bold" }
-
-[editor.error_diagnostic]
-header.border = { width = 1, top = true, color = "$border.0" }
-text_scale_factor = 0.857
-
-[editor.error_diagnostic.message]
-text = { extends = "$text.1", size = 14, color = "$status.bad" }
-highlight_text = { extends = "$text.1", size = 14, color = "$status.bad", weight = "bold" }
-
-[editor.warning_diagnostic]
-extends = "$editor.error_diagnostic"
-message.text.color = "$status.warn"
-message.highlight_text.color = "$status.warn"
-
-[editor.information_diagnostic]
-extends = "$editor.error_diagnostic"
-message.text.color = "$status.info"
-message.highlight_text.color = "$status.info"
-
-[editor.hint_diagnostic]
-extends = "$editor.error_diagnostic"
-message.text.color = "$status.info"
-message.highlight_text.color = "$status.info"
-
-[editor.invalid_error_diagnostic]
-extends = "$editor.error_diagnostic"
-message.text.color = "$text.3.color"
-message.highlight_text.color = "$text.3.color"
-
-[editor.invalid_warning_diagnostic]
-extends = "$editor.warning_diagnostic"
-message.text.color = "$text.3.color"
-message.highlight_text.color = "$text.3.color"
-
-[editor.invalid_information_diagnostic]
-extends = "$editor.information_diagnostic"
-message.text.color = "$text.3.color"
-message.highlight_text.color = "$text.3.color"
-
-[editor.invalid_hint_diagnostic]
-extends = "$editor.hint_diagnostic"
-message.text.color = "$text.3.color"
-message.highlight_text.color = "$text.3.color"
-
-[editor.autocomplete]
-background = "$surface.2"
-border = { width = 2, color = "$border.1" }
-corner_radius = 6
-padding = 6
-match_highlight = { color = "$editor.syntax.keyword.color", weight = "$editor.syntax.keyword.weight" }
-margin.left = -14
-
-[editor.autocomplete.item]
-padding = { left = 6, right = 6, top = 2, bottom = 2 }
-corner_radius = 6
-
-[editor.autocomplete.selected_item]
-extends = "$editor.autocomplete.item"
-background = "$state.selected"
-
-[editor.autocomplete.hovered_item]
-extends = "$editor.autocomplete.item"
-background = "$state.hover"
-
-[project_diagnostics]
-background = "$surface.1"
-empty_message = { extends = "$text.0", size = 18 }
-status_bar_item = { extends = "$text.2", margin.right = 10 }
-tab_icon_width = 13
-tab_icon_spacing = 4
-tab_summary_spacing = 10
-
-[search]
-match_background = "$state.highlighted_line"
-results_status = { extends = "$text.0", size = 18 }
-tab_icon_width = 14
-tab_icon_spacing = 4
-
-[search.option_button]
-extends = "$text.1"
-padding = { left = 6, right = 6, top = 1, bottom = 1 }
-corner_radius = 6
-background = "$surface.1"
-border = { width = 1, color = "$border.0" }
-margin.left = 1
-margin.right = 1
-
-[search.option_button_group]
-padding = { left = 2, right = 2 }
-
-[search.active_option_button]
-extends = "$search.option_button"
-background = "$surface.2"
-
-[search.hovered_option_button]
-extends = "$search.option_button"
-background = "$surface.2"
-
-[search.active_hovered_option_button]
-extends = "$search.option_button"
-background = "$surface.2"
-
-[search.match_index]
-extends = "$text.2"
-padding = 6
-
-[search.editor]
-min_width = 200
-max_width = 500
-background = "$surface.0"
-corner_radius = 6
-padding = { left = 14, right = 14, top = 3, bottom = 3 }
-margin = { right = 5 }
-text = "$text.0"
-placeholder_text = "$text.2"
-selection = "$selection.host"
-border = { width = 1, color = "$border.0" }
-
-[search.invalid_editor]
-extends = "$search.editor"
-border = { width = 1, color = "$status.bad" }

crates/zed/assets/themes/black.toml 🔗

@@ -1,67 +0,0 @@
-extends = "_base"
-
-[surface]
-0 = "#222222"
-1 = "#0f0b0c"
-2 = "#131415"
-
-[border]
-0 = "#000000B2"
-1 = "#FFFFFF20"
-
-[text]
-0 = { extends = "$text.base", color = "#ffffff" }
-1 = { extends = "$text.base", color = "#b3b3b3" }
-2 = { extends = "$text.base", color = "#7b7d80" }
-3 = { extends = "$text.base", color = "#66686A" }
-
-[shadow]
-0 = "#00000052"
-
-[selection]
-host = { selection = "#3B57BC55", cursor = "$text.0.color" }
-guests = [
-  { selection = "#FDF35133", cursor = "#FDF351" },
-  { selection = "#4EACAD33", cursor = "#4EACAD" },
-  { selection = "#D0453B33", cursor = "#D0453B" },
-  { selection = "#3B874B33", cursor = "#3B874B" },
-  { selection = "#BD7CB433", cursor = "#BD7CB4" },
-  { selection = "#EE823133", cursor = "#EE8231" },
-  { selection = "#5A2B9233", cursor = "#5A2B92" },
-]
-
-[status]
-good = "#4fac63"
-info = "#3c5dd4"
-warn = "#faca50"
-bad = "#b7372e"
-
-[state]
-active_line = "#161313"
-highlighted_line = "#faca5033"
-deleted_line = "#dd000036"
-inserted_line = "#00dd0036"
-hover = "#00000033"
-selected = "#00000088"
-
-[editor.syntax]
-keyword = { color = "#0086c0", weight = "bold" }
-function = "#dcdcaa"
-string = "#cb8f77"
-type = "#4ec9b0"
-number = "#b5cea8"
-comment = "#6a9955"
-property = "#4e94ce"
-variant = "#4fc1ff"
-constant = "#9cdcfe"
-title = { color = "#9cdcfe", weight = "bold" }
-emphasis = "#4ec9b0"
-"emphasis.strong" = { color = "#4ec9b0", weight = "bold" }
-link_uri = { color = "#6a9955", underline = true }
-link_text = { color = "#cb8f77", italic = true }
-list_marker = "#4e94ce"
-
-[workspace.disconnected_overlay]
-extends = "$text.base"
-color = "#ffffff"
-background = "#000000aa"

crates/zed/assets/themes/dark.json 🔗

@@ -0,0 +1,1245 @@
+{
+  "selector": {
+    "background": "#e6e6e6",
+    "corner_radius": 6,
+    "padding": 8,
+    "item": {
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 4
+      },
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Sans",
+        "color": "#595959",
+        "size": 14
+      },
+      "highlight_text": {
+        "family": "Zed Sans",
+        "color": "#2db4f3",
+        "weight": "bold",
+        "size": 14
+      }
+    },
+    "active_item": {
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 4
+      },
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Sans",
+        "color": "#262626",
+        "size": 14
+      },
+      "highlight_text": {
+        "family": "Zed Sans",
+        "color": "#2db4f3",
+        "weight": "bold",
+        "size": 14
+      },
+      "background": "#e6e6e6"
+    },
+    "border": {
+      "color": "#d9d9d9",
+      "width": 1
+    },
+    "empty": {
+      "text": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 8
+      }
+    },
+    "input_editor": {
+      "background": "#cccccc",
+      "corner_radius": 6,
+      "placeholder_text": {
+        "family": "Zed Sans",
+        "color": "#bfbfbf",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#4287f6",
+        "selection": "#4287f6"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "padding": {
+        "bottom": 7,
+        "left": 16,
+        "right": 16,
+        "top": 7
+      }
+    },
+    "margin": {
+      "bottom": 52,
+      "top": 52
+    },
+    "shadow": {
+      "blur": 16,
+      "color": "#00000052",
+      "offset": [
+        0,
+        2
+      ]
+    }
+  },
+  "workspace": {
+    "background": "#e6e6e6",
+    "leader_border_opacity": 0.7,
+    "leader_border_width": 2,
+    "tab": {
+      "height": 34,
+      "icon_close": "#808080",
+      "icon_close_active": "#0d0d0d",
+      "icon_conflict": "#f8c570",
+      "icon_dirty": "#6099f7",
+      "icon_width": 8,
+      "spacing": 10,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "left": true,
+        "bottom": true,
+        "overlay": true
+      },
+      "padding": {
+        "left": 12,
+        "right": 12
+      }
+    },
+    "active_tab": {
+      "height": 34,
+      "icon_close": "#808080",
+      "icon_close_active": "#0d0d0d",
+      "icon_conflict": "#f8c570",
+      "icon_dirty": "#6099f7",
+      "icon_width": 8,
+      "spacing": 10,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "left": true,
+        "bottom": false,
+        "overlay": true
+      },
+      "padding": {
+        "left": 12,
+        "right": 12
+      },
+      "background": "#cccccc"
+    },
+    "left_sidebar": {
+      "width": 30,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "right": true
+      },
+      "item": {
+        "height": 32,
+        "icon_color": "#808080",
+        "icon_size": 18
+      },
+      "active_item": {
+        "height": 32,
+        "icon_color": "#4d4d4d",
+        "icon_size": 18
+      },
+      "resize_handle": {
+        "background": "#d9d9d9",
+        "padding": {
+          "left": 1
+        }
+      }
+    },
+    "right_sidebar": {
+      "width": 30,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "left": true
+      },
+      "item": {
+        "height": 32,
+        "icon_color": "#808080",
+        "icon_size": 18
+      },
+      "active_item": {
+        "height": 32,
+        "icon_color": "#4d4d4d",
+        "icon_size": 18
+      },
+      "resize_handle": {
+        "background": "#d9d9d9",
+        "padding": {
+          "left": 1
+        }
+      }
+    },
+    "pane_divider": {
+      "color": "#d9d9d9",
+      "width": 1
+    },
+    "status_bar": {
+      "height": 24,
+      "item_spacing": 8,
+      "padding": {
+        "left": 6,
+        "right": 6
+      },
+      "cursor_position": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "diagnostic_message": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "lsp_message": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      }
+    },
+    "titlebar": {
+      "avatar_width": 18,
+      "height": 32,
+      "share_icon_color": "#808080",
+      "share_icon_active_color": "#0d0d0d",
+      "title": {
+        "family": "Zed Sans",
+        "color": "#262626",
+        "size": 14
+      },
+      "avatar": {
+        "corner_radius": 10,
+        "border": {
+          "color": "#00000088",
+          "width": 1
+        }
+      },
+      "avatar_ribbon": {
+        "height": 3,
+        "width": 12
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "bottom": true
+      },
+      "sign_in_prompt": {
+        "family": "Zed Sans",
+        "color": "#595959",
+        "size": 13,
+        "underline": true,
+        "padding": {
+          "right": 8
+        }
+      },
+      "hovered_sign_in_prompt": {
+        "family": "Zed Mono",
+        "color": "#000000",
+        "size": 16,
+        "underline": true,
+        "padding": {
+          "right": 8
+        }
+      },
+      "offline_icon": {
+        "color": "#999999",
+        "width": 16,
+        "padding": {
+          "right": 4
+        }
+      },
+      "outdated_warning": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 13
+      }
+    },
+    "toolbar": {
+      "height": 34,
+      "background": "#cccccc",
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "bottom": true
+      },
+      "item_spacing": 8,
+      "padding": {
+        "left": 16,
+        "right": 8,
+        "top": 4,
+        "bottom": 4
+      }
+    },
+    "breadcrumbs": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "padding": {
+        "left": 6
+      }
+    },
+    "disconnected_overlay": {
+      "family": "Zed Sans",
+      "color": "#ffffff",
+      "size": 14,
+      "background": "#000000aa"
+    }
+  },
+  "editor": {
+    "text_color": "#595959",
+    "background": "#cccccc",
+    "active_line_background": "#000000",
+    "code_actions_indicator": "#808080",
+    "diff_background_deleted": "#f78c8c",
+    "diff_background_inserted": "#22c55e",
+    "document_highlight_read_background": "#e6e6e6",
+    "document_highlight_write_background": "#e6e6e6",
+    "error_color": "#f78c8c",
+    "gutter_background": "#cccccc",
+    "gutter_padding_factor": 2.5,
+    "highlighted_line_background": "#000000",
+    "line_number": "#000000",
+    "line_number_active": "#000000",
+    "rename_fade": 0.6,
+    "unnecessary_code_fade": 0.5,
+    "selection": {
+      "cursor": "#4287f6",
+      "selection": "#4287f6"
+    },
+    "guest_selections": [
+      {
+        "cursor": "#777af4",
+        "selection": "#777af4"
+      },
+      {
+        "cursor": "#23d464",
+        "selection": "#23d464"
+      },
+      {
+        "cursor": "#f98a3d",
+        "selection": "#f98a3d"
+      },
+      {
+        "cursor": "#b671f8",
+        "selection": "#b671f8"
+      },
+      {
+        "cursor": "#16ddc7",
+        "selection": "#16ddc7"
+      },
+      {
+        "cursor": "#f58ac0",
+        "selection": "#f58ac0"
+      },
+      {
+        "cursor": "#f6bc09",
+        "selection": "#f6bc09"
+      }
+    ],
+    "autocomplete": {
+      "background": "#bfbfbf",
+      "corner_radius": 6,
+      "padding": 6,
+      "border": {
+        "color": "#b3b3b3",
+        "width": 1
+      },
+      "item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        }
+      },
+      "hovered_item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        },
+        "background": "#bfbfbf"
+      },
+      "margin": {
+        "left": -14
+      },
+      "match_highlight": {
+        "color": "#59c3f5",
+        "weight": "normal"
+      },
+      "selected_item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        },
+        "background": "#bfbfbf"
+      }
+    },
+    "diagnostic_header": {
+      "background": "#e6e6e6",
+      "icon_width_factor": 1.5,
+      "text_scale_factor": 0.857,
+      "border": {
+        "color": "#b3b3b3",
+        "width": 1,
+        "bottom": true,
+        "top": true
+      },
+      "code": {
+        "family": "Zed Mono",
+        "color": "#8c8c8c",
+        "size": 14,
+        "margin": {
+          "left": 10
+        }
+      },
+      "message": {
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#262626",
+          "size": 14,
+          "weight": "bold"
+        },
+        "text": {
+          "family": "Zed Sans",
+          "color": "#595959",
+          "size": 14
+        }
+      }
+    },
+    "diagnostic_path_header": {
+      "background": "#000000",
+      "text_scale_factor": 0.857,
+      "filename": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 14
+      },
+      "path": {
+        "family": "Zed Mono",
+        "color": "#8c8c8c",
+        "size": 14,
+        "margin": {
+          "left": 12
+        }
+      }
+    },
+    "error_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#f78c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#f78c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "warning_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#f8c570",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#f8c570",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "information_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#6099f7",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#6099f7",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "hint_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#6099f7",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#6099f7",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_error_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_hint_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_information_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_warning_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "syntax": {}
+  },
+  "project_diagnostics": {
+    "background": "#cccccc",
+    "tab_icon_spacing": 4,
+    "tab_icon_width": 13,
+    "tab_summary_spacing": 10,
+    "empty_message": {
+      "family": "Zed Sans",
+      "color": "#262626",
+      "size": 14
+    },
+    "status_bar_item": {
+      "family": "Zed Sans",
+      "color": "#8c8c8c",
+      "size": 14,
+      "margin": {
+        "right": 10
+      }
+    }
+  },
+  "project_panel": {
+    "padding": {
+      "top": 6
+    },
+    "entry": {
+      "height": 22,
+      "icon_color": "#999999",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16
+      }
+    },
+    "hovered_entry": {
+      "height": 22,
+      "background": "#cccccc",
+      "icon_color": "#999999",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16
+      }
+    },
+    "selected_entry": {
+      "height": 22,
+      "icon_color": "#999999",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      }
+    },
+    "hovered_selected_entry": {
+      "height": 22,
+      "background": "#cccccc",
+      "icon_color": "#999999",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      }
+    }
+  },
+  "chat_panel": {
+    "padding": {
+      "top": 12,
+      "left": 12,
+      "bottom": 12,
+      "right": 12
+    },
+    "channel_name": {
+      "family": "Zed Sans",
+      "color": "#262626",
+      "weight": "bold",
+      "size": 14
+    },
+    "channel_name_hash": {
+      "family": "Zed Sans",
+      "color": "#8c8c8c",
+      "size": 14,
+      "padding": {
+        "right": 8
+      }
+    },
+    "channel_select": {
+      "header": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#262626",
+          "size": 14
+        },
+        "padding": {
+          "bottom": 4,
+          "left": 0
+        },
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#595959",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "hovered_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#595959",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "background": "#cccccc",
+        "corner_radius": 6
+      },
+      "active_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#262626",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "hovered_active_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#262626",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "background": "#cccccc",
+        "corner_radius": 6
+      },
+      "menu": {
+        "background": "#e6e6e6",
+        "corner_radius": 6,
+        "padding": 4,
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1
+        },
+        "shadow": {
+          "blur": 16,
+          "color": "#00000052",
+          "offset": [
+            0,
+            2
+          ]
+        }
+      }
+    },
+    "sign_in_prompt": {
+      "family": "Zed Sans",
+      "color": "#595959",
+      "underline": true,
+      "size": 14
+    },
+    "hovered_sign_in_prompt": {
+      "family": "Zed Sans",
+      "color": "#262626",
+      "underline": true,
+      "size": 14
+    },
+    "message": {
+      "body": {
+        "family": "Zed Sans",
+        "color": "#595959",
+        "size": 14
+      },
+      "timestamp": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 6
+      },
+      "sender": {
+        "family": "Zed Sans",
+        "color": "#262626",
+        "weight": "bold",
+        "size": 14,
+        "margin": {
+          "right": 8
+        }
+      }
+    },
+    "pending_message": {
+      "body": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "timestamp": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 6
+      },
+      "sender": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "weight": "bold",
+        "size": 14,
+        "margin": {
+          "right": 8
+        }
+      }
+    },
+    "input_editor": {
+      "background": "#cccccc",
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#8c8c8c",
+        "size": 16
+      },
+      "selection": {
+        "cursor": "#4287f6",
+        "selection": "#4287f6"
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "padding": {
+        "bottom": 7,
+        "left": 8,
+        "right": 8,
+        "top": 7
+      }
+    }
+  },
+  "contacts_panel": {
+    "padding": {
+      "top": 12,
+      "left": 12,
+      "bottom": 12,
+      "right": 12
+    },
+    "host_row_height": 28,
+    "tree_branch_color": "#bfbfbf",
+    "tree_branch_width": 1,
+    "host_avatar": {
+      "corner_radius": 10,
+      "width": 18
+    },
+    "host_username": {
+      "family": "Zed Mono",
+      "color": "#8c8c8c",
+      "size": 16,
+      "padding": {
+        "left": 8
+      }
+    },
+    "project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "shared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "hovered_shared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "background": "#000000",
+      "corner_radius": 6
+    },
+    "unshared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "hovered_unshared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "background": "#000000",
+      "corner_radius": 6
+    }
+  },
+  "search": {
+    "match_background": "#000000",
+    "tab_icon_spacing": 4,
+    "tab_icon_width": 14,
+    "active_hovered_option_button": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "background": "#bfbfbf",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "active_option_button": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "background": "#bfbfbf",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "editor": {
+      "background": "#e6e6e6",
+      "corner_radius": 6,
+      "min_width": 200,
+      "max_width": 500,
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#bfbfbf",
+        "size": 16
+      },
+      "selection": {
+        "cursor": "#4287f6",
+        "selection": "#4287f6"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "right": 5
+      },
+      "padding": {
+        "top": 3,
+        "bottom": 3,
+        "left": 14,
+        "right": 14
+      }
+    },
+    "hovered_option_button": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "background": "#bfbfbf",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "invalid_editor": {
+      "background": "#e6e6e6",
+      "corner_radius": 6,
+      "min_width": 200,
+      "max_width": 500,
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#bfbfbf",
+        "size": 16
+      },
+      "selection": {
+        "cursor": "#4287f6",
+        "selection": "#4287f6"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "border": {
+        "color": "#ffffff",
+        "width": 1
+      },
+      "margin": {
+        "right": 5
+      },
+      "padding": {
+        "top": 3,
+        "bottom": 3,
+        "left": 14,
+        "right": 14
+      }
+    },
+    "match_index": {
+      "family": "Zed Mono",
+      "color": "#8c8c8c",
+      "size": 16,
+      "padding": 6
+    },
+    "option_button": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "background": "#cccccc",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "option_button_group": {
+      "padding": {
+        "left": 2,
+        "right": 2
+      }
+    },
+    "results_status": {
+      "family": "Zed Mono",
+      "color": "#262626",
+      "size": 18
+    }
+  },
+  "breadcrumbs": {
+    "family": "Zed Sans",
+    "color": "#262626",
+    "size": 14,
+    "padding": {
+      "left": 6
+    }
+  }
+}

crates/zed/assets/themes/dark.toml 🔗

@@ -1,67 +0,0 @@
-extends = "_base"
-
-[surface]
-0 = "#283340"
-1 = "#1C2733"
-2 = "#1C2733"
-
-[border]
-0 = "#1B222B"
-1 = "#FFFFFF20"
-
-[text]
-0 = { extends = "$text.base", color = "#FFFFFF" }
-1 = { extends = "$text.base", color = "#CDD1E2" }
-2 = { extends = "$text.base", color = "#9BA8BE" }
-3 = { extends = "$text.base", color = "#6E7483" }
-
-[shadow]
-0 = "#00000052"
-
-[selection]
-host = { selection = "#3B57BC55", cursor = "$text.0.color" }
-guests = [
-  { selection = "#FDF35133", cursor = "#FDF351" },
-  { selection = "#4EACAD33", cursor = "#4EACAD" },
-  { selection = "#D0453B33", cursor = "#D0453B" },
-  { selection = "#3B874B33", cursor = "#3B874B" },
-  { selection = "#BD7CB433", cursor = "#BD7CB4" },
-  { selection = "#EE823133", cursor = "#EE8231" },
-  { selection = "#5A2B9233", cursor = "#5A2B92" },
-]
-
-[status]
-good = "#4fac63"
-info = "#3c5dd4"
-warn = "#faca50"
-bad = "#b7372e"
-
-[state]
-active_line = "#00000022"
-highlighted_line = "#faca5033"
-deleted_line = "#dd000036"
-inserted_line = "#00dd0036"
-hover = "#00000033"
-selected = "#00000088"
-
-[editor.syntax]
-keyword = { color = "#0086c0", weight = "bold" }
-function = "#dcdcaa"
-string = "#cb8f77"
-type = "#4ec9b0"
-number = "#b5cea8"
-comment = "#6a9955"
-property = "#4e94ce"
-variant = "#4fc1ff"
-constant = "#9cdcfe"
-title = { color = "#9cdcfe", weight = "bold" }
-emphasis = "#4ec9b0"
-"emphasis.strong" = { color = "#4ec9b0", weight = "bold" }
-link_uri = { color = "#6a9955", underline = true }
-link_text = { color = "#cb8f77", italic = true }
-list_marker = "#4e94ce"
-
-[workspace.disconnected_overlay]
-extends = "$text.base"
-color = "#ffffff"
-background = "#000000aa"

crates/zed/assets/themes/light.json 🔗

@@ -0,0 +1,1245 @@
+{
+  "selector": {
+    "background": "#e6e6e6",
+    "corner_radius": 6,
+    "padding": 8,
+    "item": {
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 4
+      },
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Sans",
+        "color": "#595959",
+        "size": 14
+      },
+      "highlight_text": {
+        "family": "Zed Sans",
+        "color": "#2db4f3",
+        "weight": "bold",
+        "size": 14
+      }
+    },
+    "active_item": {
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 4
+      },
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Sans",
+        "color": "#262626",
+        "size": 14
+      },
+      "highlight_text": {
+        "family": "Zed Sans",
+        "color": "#2db4f3",
+        "weight": "bold",
+        "size": 14
+      },
+      "background": "#e6e6e6"
+    },
+    "border": {
+      "color": "#d9d9d9",
+      "width": 1
+    },
+    "empty": {
+      "text": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 8
+      }
+    },
+    "input_editor": {
+      "background": "#cccccc",
+      "corner_radius": 6,
+      "placeholder_text": {
+        "family": "Zed Sans",
+        "color": "#bfbfbf",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#4287f6",
+        "selection": "#4287f6"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "padding": {
+        "bottom": 7,
+        "left": 16,
+        "right": 16,
+        "top": 7
+      }
+    },
+    "margin": {
+      "bottom": 52,
+      "top": 52
+    },
+    "shadow": {
+      "blur": 16,
+      "color": "#00000052",
+      "offset": [
+        0,
+        2
+      ]
+    }
+  },
+  "workspace": {
+    "background": "#e6e6e6",
+    "leader_border_opacity": 0.7,
+    "leader_border_width": 2,
+    "tab": {
+      "height": 34,
+      "icon_close": "#808080",
+      "icon_close_active": "#0d0d0d",
+      "icon_conflict": "#f8c570",
+      "icon_dirty": "#6099f7",
+      "icon_width": 8,
+      "spacing": 10,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "left": true,
+        "bottom": true,
+        "overlay": true
+      },
+      "padding": {
+        "left": 12,
+        "right": 12
+      }
+    },
+    "active_tab": {
+      "height": 34,
+      "icon_close": "#808080",
+      "icon_close_active": "#0d0d0d",
+      "icon_conflict": "#f8c570",
+      "icon_dirty": "#6099f7",
+      "icon_width": 8,
+      "spacing": 10,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "left": true,
+        "bottom": false,
+        "overlay": true
+      },
+      "padding": {
+        "left": 12,
+        "right": 12
+      },
+      "background": "#cccccc"
+    },
+    "left_sidebar": {
+      "width": 30,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "right": true
+      },
+      "item": {
+        "height": 32,
+        "icon_color": "#808080",
+        "icon_size": 18
+      },
+      "active_item": {
+        "height": 32,
+        "icon_color": "#4d4d4d",
+        "icon_size": 18
+      },
+      "resize_handle": {
+        "background": "#d9d9d9",
+        "padding": {
+          "left": 1
+        }
+      }
+    },
+    "right_sidebar": {
+      "width": 30,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "left": true
+      },
+      "item": {
+        "height": 32,
+        "icon_color": "#808080",
+        "icon_size": 18
+      },
+      "active_item": {
+        "height": 32,
+        "icon_color": "#4d4d4d",
+        "icon_size": 18
+      },
+      "resize_handle": {
+        "background": "#d9d9d9",
+        "padding": {
+          "left": 1
+        }
+      }
+    },
+    "pane_divider": {
+      "color": "#d9d9d9",
+      "width": 1
+    },
+    "status_bar": {
+      "height": 24,
+      "item_spacing": 8,
+      "padding": {
+        "left": 6,
+        "right": 6
+      },
+      "cursor_position": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "diagnostic_message": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "lsp_message": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      }
+    },
+    "titlebar": {
+      "avatar_width": 18,
+      "height": 32,
+      "share_icon_color": "#808080",
+      "share_icon_active_color": "#0d0d0d",
+      "title": {
+        "family": "Zed Sans",
+        "color": "#262626",
+        "size": 14
+      },
+      "avatar": {
+        "corner_radius": 10,
+        "border": {
+          "color": "#00000088",
+          "width": 1
+        }
+      },
+      "avatar_ribbon": {
+        "height": 3,
+        "width": 12
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "bottom": true
+      },
+      "sign_in_prompt": {
+        "family": "Zed Sans",
+        "color": "#595959",
+        "size": 13,
+        "underline": true,
+        "padding": {
+          "right": 8
+        }
+      },
+      "hovered_sign_in_prompt": {
+        "family": "Zed Mono",
+        "color": "#000000",
+        "size": 16,
+        "underline": true,
+        "padding": {
+          "right": 8
+        }
+      },
+      "offline_icon": {
+        "color": "#999999",
+        "width": 16,
+        "padding": {
+          "right": 4
+        }
+      },
+      "outdated_warning": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 13
+      }
+    },
+    "toolbar": {
+      "height": 34,
+      "background": "#cccccc",
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1,
+        "bottom": true
+      },
+      "item_spacing": 8,
+      "padding": {
+        "left": 16,
+        "right": 8,
+        "top": 4,
+        "bottom": 4
+      }
+    },
+    "breadcrumbs": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "padding": {
+        "left": 6
+      }
+    },
+    "disconnected_overlay": {
+      "family": "Zed Sans",
+      "color": "#ffffff",
+      "size": 14,
+      "background": "#000000aa"
+    }
+  },
+  "editor": {
+    "text_color": "#595959",
+    "background": "#cccccc",
+    "active_line_background": "#000000",
+    "code_actions_indicator": "#808080",
+    "diff_background_deleted": "#f78c8c",
+    "diff_background_inserted": "#22c55e",
+    "document_highlight_read_background": "#e6e6e6",
+    "document_highlight_write_background": "#e6e6e6",
+    "error_color": "#f78c8c",
+    "gutter_background": "#cccccc",
+    "gutter_padding_factor": 2.5,
+    "highlighted_line_background": "#000000",
+    "line_number": "#000000",
+    "line_number_active": "#000000",
+    "rename_fade": 0.6,
+    "unnecessary_code_fade": 0.5,
+    "selection": {
+      "cursor": "#4287f6",
+      "selection": "#4287f6"
+    },
+    "guest_selections": [
+      {
+        "cursor": "#777af4",
+        "selection": "#777af4"
+      },
+      {
+        "cursor": "#23d464",
+        "selection": "#23d464"
+      },
+      {
+        "cursor": "#f98a3d",
+        "selection": "#f98a3d"
+      },
+      {
+        "cursor": "#b671f8",
+        "selection": "#b671f8"
+      },
+      {
+        "cursor": "#16ddc7",
+        "selection": "#16ddc7"
+      },
+      {
+        "cursor": "#f58ac0",
+        "selection": "#f58ac0"
+      },
+      {
+        "cursor": "#f6bc09",
+        "selection": "#f6bc09"
+      }
+    ],
+    "autocomplete": {
+      "background": "#bfbfbf",
+      "corner_radius": 6,
+      "padding": 6,
+      "border": {
+        "color": "#b3b3b3",
+        "width": 1
+      },
+      "item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        }
+      },
+      "hovered_item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        },
+        "background": "#bfbfbf"
+      },
+      "margin": {
+        "left": -14
+      },
+      "match_highlight": {
+        "color": "#59c3f5",
+        "weight": "normal"
+      },
+      "selected_item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        },
+        "background": "#bfbfbf"
+      }
+    },
+    "diagnostic_header": {
+      "background": "#e6e6e6",
+      "icon_width_factor": 1.5,
+      "text_scale_factor": 0.857,
+      "border": {
+        "color": "#b3b3b3",
+        "width": 1,
+        "bottom": true,
+        "top": true
+      },
+      "code": {
+        "family": "Zed Mono",
+        "color": "#8c8c8c",
+        "size": 14,
+        "margin": {
+          "left": 10
+        }
+      },
+      "message": {
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#262626",
+          "size": 14,
+          "weight": "bold"
+        },
+        "text": {
+          "family": "Zed Sans",
+          "color": "#595959",
+          "size": 14
+        }
+      }
+    },
+    "diagnostic_path_header": {
+      "background": "#000000",
+      "text_scale_factor": 0.857,
+      "filename": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 14
+      },
+      "path": {
+        "family": "Zed Mono",
+        "color": "#8c8c8c",
+        "size": 14,
+        "margin": {
+          "left": 12
+        }
+      }
+    },
+    "error_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#f78c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#f78c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "warning_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#f8c570",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#f8c570",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "information_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#6099f7",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#6099f7",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "hint_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#6099f7",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#6099f7",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_error_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_hint_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_information_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_warning_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "syntax": {}
+  },
+  "project_diagnostics": {
+    "background": "#cccccc",
+    "tab_icon_spacing": 4,
+    "tab_icon_width": 13,
+    "tab_summary_spacing": 10,
+    "empty_message": {
+      "family": "Zed Sans",
+      "color": "#262626",
+      "size": 14
+    },
+    "status_bar_item": {
+      "family": "Zed Sans",
+      "color": "#8c8c8c",
+      "size": 14,
+      "margin": {
+        "right": 10
+      }
+    }
+  },
+  "project_panel": {
+    "padding": {
+      "top": 6
+    },
+    "entry": {
+      "height": 22,
+      "icon_color": "#999999",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16
+      }
+    },
+    "hovered_entry": {
+      "height": 22,
+      "background": "#cccccc",
+      "icon_color": "#999999",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16
+      }
+    },
+    "selected_entry": {
+      "height": 22,
+      "icon_color": "#999999",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      }
+    },
+    "hovered_selected_entry": {
+      "height": 22,
+      "background": "#cccccc",
+      "icon_color": "#999999",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      }
+    }
+  },
+  "chat_panel": {
+    "padding": {
+      "top": 12,
+      "left": 12,
+      "bottom": 12,
+      "right": 12
+    },
+    "channel_name": {
+      "family": "Zed Sans",
+      "color": "#262626",
+      "weight": "bold",
+      "size": 14
+    },
+    "channel_name_hash": {
+      "family": "Zed Sans",
+      "color": "#8c8c8c",
+      "size": 14,
+      "padding": {
+        "right": 8
+      }
+    },
+    "channel_select": {
+      "header": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#262626",
+          "size": 14
+        },
+        "padding": {
+          "bottom": 4,
+          "left": 0
+        },
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#595959",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "hovered_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#595959",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "background": "#cccccc",
+        "corner_radius": 6
+      },
+      "active_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#262626",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "hovered_active_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#262626",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#8c8c8c",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "background": "#cccccc",
+        "corner_radius": 6
+      },
+      "menu": {
+        "background": "#e6e6e6",
+        "corner_radius": 6,
+        "padding": 4,
+        "border": {
+          "color": "#d9d9d9",
+          "width": 1
+        },
+        "shadow": {
+          "blur": 16,
+          "color": "#00000052",
+          "offset": [
+            0,
+            2
+          ]
+        }
+      }
+    },
+    "sign_in_prompt": {
+      "family": "Zed Sans",
+      "color": "#595959",
+      "underline": true,
+      "size": 14
+    },
+    "hovered_sign_in_prompt": {
+      "family": "Zed Sans",
+      "color": "#262626",
+      "underline": true,
+      "size": 14
+    },
+    "message": {
+      "body": {
+        "family": "Zed Sans",
+        "color": "#595959",
+        "size": 14
+      },
+      "timestamp": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 6
+      },
+      "sender": {
+        "family": "Zed Sans",
+        "color": "#262626",
+        "weight": "bold",
+        "size": 14,
+        "margin": {
+          "right": 8
+        }
+      }
+    },
+    "pending_message": {
+      "body": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "timestamp": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 6
+      },
+      "sender": {
+        "family": "Zed Sans",
+        "color": "#8c8c8c",
+        "weight": "bold",
+        "size": 14,
+        "margin": {
+          "right": 8
+        }
+      }
+    },
+    "input_editor": {
+      "background": "#cccccc",
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#8c8c8c",
+        "size": 16
+      },
+      "selection": {
+        "cursor": "#4287f6",
+        "selection": "#4287f6"
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "padding": {
+        "bottom": 7,
+        "left": 8,
+        "right": 8,
+        "top": 7
+      }
+    }
+  },
+  "contacts_panel": {
+    "padding": {
+      "top": 12,
+      "left": 12,
+      "bottom": 12,
+      "right": 12
+    },
+    "host_row_height": 28,
+    "tree_branch_color": "#bfbfbf",
+    "tree_branch_width": 1,
+    "host_avatar": {
+      "corner_radius": 10,
+      "width": 18
+    },
+    "host_username": {
+      "family": "Zed Mono",
+      "color": "#8c8c8c",
+      "size": 16,
+      "padding": {
+        "left": 8
+      }
+    },
+    "project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "shared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "hovered_shared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "background": "#000000",
+      "corner_radius": 6
+    },
+    "unshared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "hovered_unshared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#595959",
+        "size": 16,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "background": "#000000",
+      "corner_radius": 6
+    }
+  },
+  "search": {
+    "match_background": "#000000",
+    "tab_icon_spacing": 4,
+    "tab_icon_width": 14,
+    "active_hovered_option_button": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "background": "#bfbfbf",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "active_option_button": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "background": "#bfbfbf",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "editor": {
+      "background": "#e6e6e6",
+      "corner_radius": 6,
+      "min_width": 200,
+      "max_width": 500,
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#bfbfbf",
+        "size": 16
+      },
+      "selection": {
+        "cursor": "#4287f6",
+        "selection": "#4287f6"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "right": 5
+      },
+      "padding": {
+        "top": 3,
+        "bottom": 3,
+        "left": 14,
+        "right": 14
+      }
+    },
+    "hovered_option_button": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "background": "#bfbfbf",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "invalid_editor": {
+      "background": "#e6e6e6",
+      "corner_radius": 6,
+      "min_width": 200,
+      "max_width": 500,
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#bfbfbf",
+        "size": 16
+      },
+      "selection": {
+        "cursor": "#4287f6",
+        "selection": "#4287f6"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#262626",
+        "size": 16
+      },
+      "border": {
+        "color": "#ffffff",
+        "width": 1
+      },
+      "margin": {
+        "right": 5
+      },
+      "padding": {
+        "top": 3,
+        "bottom": 3,
+        "left": 14,
+        "right": 14
+      }
+    },
+    "match_index": {
+      "family": "Zed Mono",
+      "color": "#8c8c8c",
+      "size": 16,
+      "padding": 6
+    },
+    "option_button": {
+      "family": "Zed Mono",
+      "color": "#595959",
+      "size": 16,
+      "background": "#cccccc",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d9d9d9",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "option_button_group": {
+      "padding": {
+        "left": 2,
+        "right": 2
+      }
+    },
+    "results_status": {
+      "family": "Zed Mono",
+      "color": "#262626",
+      "size": 18
+    }
+  },
+  "breadcrumbs": {
+    "family": "Zed Sans",
+    "color": "#262626",
+    "size": 14,
+    "padding": {
+      "left": 6
+    }
+  }
+}

crates/zed/assets/themes/light.toml 🔗

@@ -1,67 +0,0 @@
-extends = "_base"
-
-[surface]
-0 = "#EAEAEB"
-1 = "#FAFAFA"
-2 = "#FFFFFF"
-
-[border]
-0 = "#DDDDDC"
-1 = "#0000000F"
-
-[text]
-0 = { extends = "$text.base", color = "#000000" }
-1 = { extends = "$text.base", color = "#29292B" }
-2 = { extends = "$text.base", color = "#7E7E83" }
-3 = { extends = "$text.base", color = "#939393" }
-
-[shadow]
-0 = "#0000000D"
-
-[selection]
-host = { selection = "#3B57BC55", cursor = "$text.0.color" }
-guests = [
-  { selection = "#D0453B33", cursor = "#D0453B" },
-  { selection = "#3B874B33", cursor = "#3B874B" },
-  { selection = "#BD7CB433", cursor = "#BD7CB4" },
-  { selection = "#EE823133", cursor = "#EE8231" },
-  { selection = "#5A2B9233", cursor = "#5A2B92" },
-  { selection = "#FDF35133", cursor = "#FDF351" },
-  { selection = "#4EACAD33", cursor = "#4EACAD" },
-]
-
-[status]
-good = "#4fac63"
-info = "#3c5dd4"
-warn = "#faca50"
-bad = "#b7372e"
-
-[state]
-active_line = "#00000008"
-highlighted_line = "#faca5033"
-deleted_line = "#dd000036"
-inserted_line = "#00dd0036"
-hover = "#0000000D"
-selected = "#0000001c"
-
-[editor.syntax]
-keyword = { color = "#0000fa", weight = "bold" }
-function = "#795e26"
-string = "#a82121"
-type = "#267f29"
-number = "#b5cea8"
-comment = "#6a9955"
-property = "#4e94ce"
-variant = "#4fc1ff"
-constant = "#5a9ccc"
-title = { color = "#5a9ccc", weight = "bold" }
-emphasis = "#267f29"
-"emphasis.strong" = { color = "#267f29", weight = "bold" }
-link_uri = { color = "#6a9955", underline = true }
-link_text = { color = "#a82121", italic = true }
-list_marker = "#4e94ce"
-
-[workspace.disconnected_overlay]
-extends = "$text.base"
-color = "#ffffff"
-background = "#000000cc"

crates/zed/src/zed.rs 🔗

@@ -988,7 +988,8 @@ mod tests {
         lazy_static::lazy_static! {
             static ref DEFAULT_THEME: parking_lot::Mutex<Option<Arc<Theme>>> = Default::default();
             static ref FONTS: Vec<Arc<Vec<u8>>> = vec![
-                Assets.load("fonts/zed-sans/zed-sans-extended.ttf").unwrap().to_vec().into()
+                Assets.load("fonts/zed-sans/zed-sans-extended.ttf").unwrap().to_vec().into(),
+                Assets.load("fonts/zed-mono/zed-mono-extended.ttf").unwrap().to_vec().into(),
             ];
         }
 

styles/buildThemes.ts 🔗

@@ -7,11 +7,11 @@ import decamelizeTree from "./utils/decamelizeTree";
 
 const themes = [dark, light];
 for (let theme of themes) {
-  let styleTree = decamelizeTree(app(theme));
-  let styleTreeJSON = JSON.stringify(styleTree, null, 2);
-  let outPath = path.resolve(
-    `${__dirname}/../crates/zed/assets/themes/${theme.name}.json`
-  );
-  fs.writeFileSync(outPath, styleTreeJSON);
-  console.log(`Generated ${outPath}`);
+    let styleTree = decamelizeTree(app(theme));
+    let styleTreeJSON = JSON.stringify(styleTree, null, 2);
+    let outPath = path.resolve(
+        `${__dirname}/../crates/zed/assets/themes/${theme.name}.json`
+    );
+    fs.writeFileSync(outPath, styleTreeJSON);
+    console.log(`Generated ${outPath}`);
 }

styles/styleTree/app.ts 🔗

@@ -1,6 +1,7 @@
 import Theme from "../themes/theme";
 import chatPanel from "./chatPanel";
 import { backgroundColor, borderColor, text } from "./components";
+import contactsPanel from "./contactsPanel";
 import editor from "./editor";
 import projectPanel from "./projectPanel";
 import search from "./search";
@@ -8,83 +9,38 @@ import selectorModal from "./selectorModal";
 import workspace from "./workspace";
 
 export const panel = {
-  padding: { top: 12, left: 12, bottom: 12, right: 12 },
+    padding: { top: 12, left: 12, bottom: 12, right: 12 },
 };
 
 export default function app(theme: Theme): Object {
-  return {
-    selector: selectorModal(theme),
-    workspace: workspace(theme),
-    editor: editor(theme),
-    projectDiagnostics: {
-      background: backgroundColor(theme, 300),
-      tabIconSpacing: 4,
-      tabIconWidth: 13,
-      tabSummarySpacing: 10,
-      emptyMessage: {
-        ...text(theme, "sans", "primary", { size: "lg" }),
-      },
-      statusBarItem: {
-        ...text(theme, "sans", "muted"),
-        margin: {
-          right: 10,
+    return {
+        selector: selectorModal(theme),
+        workspace: workspace(theme),
+        editor: editor(theme),
+        projectDiagnostics: {
+            background: backgroundColor(theme, 300),
+            tabIconSpacing: 4,
+            tabIconWidth: 13,
+            tabSummarySpacing: 10,
+            emptyMessage: {
+                ...text(theme, "sans", "primary", { size: "lg" }),
+            },
+            statusBarItem: {
+                ...text(theme, "sans", "muted"),
+                margin: {
+                    right: 10,
+                },
+            },
         },
-      },
-    },
-    projectPanel: projectPanel(theme),
-    chatPanel: chatPanel(theme),
-    contactsPanel: {
-      ...panel,
-      hostRowHeight: 28,
-      treeBranchColor: borderColor(theme, "muted"),
-      treeBranchWidth: 1,
-      hostAvatar: {
-        cornerRadius: 10,
-        width: 18,
-      },
-      hostUsername: {
-        ...text(theme, "mono", "muted"),
-        padding: {
-          left: 8,
-        },
-      },
-      hoveredSharedProject: {
-        extends: "$contacts_panel.sharedProject",
-        background: theme.editor.line.active.value,
-        cornerRadius: 6,
-      },
-      hoveredUnsharedProject: {
-        extends: "$contacts_panel.unsharedProject",
-        background: theme.editor.line.active.value,
-        cornerRadius: 6,
-      },
-      project: {
-        guestAvatarSpacing: 4,
-        height: 24,
-        guestAvatar: {
-          cornerRadius: 8,
-          width: 14,
-        },
-        name: {
-          extends: text(theme, "mono", "secondary"),
-          margin: {
-            right: 6,
-          },
-        },
-        padding: {
-          left: 8,
-        },
-      },
-      sharedProject: {
-        extends: "$contactsPanel.project",
-        name: {
-          color: text(theme, "mono", "primary"),
-        },
-      },
-      unsharedProject: {
-        extends: "$contactsPanel.project",
-      },
-    },
-    search: search(theme),
-  };
+        projectPanel: projectPanel(theme),
+        chatPanel: chatPanel(theme),
+        contactsPanel: contactsPanel(theme),
+        search: search(theme),
+        breadcrumbs: {
+            ...text(theme, "sans", "primary"),
+            padding: {
+                left: 6,
+            },
+        }
+    };
 }

styles/styleTree/components.ts 🔗

@@ -1,25 +1,25 @@
 import chroma from "chroma-js";
-import Theme, { BackgroundColor, Weight } from "../themes/theme";
-import core from "../tokens/core";
+import Theme, { BackgroundColor } from "../themes/theme";
+import { fontFamilies, fontSizes, FontWeight } from "../tokens";
 import { Color } from "../utils/color";
 
 export type TextColor = keyof Theme["textColor"];
 
 export function text(
   theme: Theme,
-  fontFamily: keyof typeof core.fontFamily,
+  fontFamily: keyof typeof fontFamilies,
   color: TextColor,
   properties?: {
-    size?: keyof typeof core["fontSize"];
-    weight?: Weight;
+    size?: keyof typeof fontSizes;
+    weight?: FontWeight;
     underline?: boolean;
   }
 ) {
   const sizeKey = properties?.size || fontFamily === "sans" ? "sm" : "md";
-  const size = core.fontSize[sizeKey].value;
+  const size = fontSizes[sizeKey].value;
 
   return {
-    family: core.fontFamily[fontFamily],
+    family: fontFamilies[fontFamily].value,
     color: theme.textColor[color].value,
     ...properties,
     size,

styles/styleTree/contactsPanel.ts 🔗

@@ -0,0 +1,61 @@
+import Theme from "../themes/theme";
+import { panel } from "./app";
+import { borderColor, text } from "./components";
+
+export default function(theme: Theme) {
+    const project = {
+        guestAvatarSpacing: 4,
+        height: 24,
+        guestAvatar: {
+            cornerRadius: 8,
+            width: 14,
+        },
+        name: {
+            ...text(theme, "mono", "secondary"),
+            margin: {
+                right: 6,
+            },
+        },
+        padding: {
+            left: 8,
+        },
+    };
+
+    const sharedProject = {
+        ...project,
+        name: {
+            ...project.name,
+            ...text(theme, "mono", "primary"),
+        },
+    };
+
+    return {
+        ...panel,
+        hostRowHeight: 28,
+        treeBranchColor: borderColor(theme, "muted"),
+        treeBranchWidth: 1,
+        hostAvatar: {
+            cornerRadius: 10,
+            width: 18,
+        },
+        hostUsername: {
+            ...text(theme, "mono", "muted"),
+            padding: {
+                left: 8,
+            },
+        },
+        project,
+        sharedProject,
+        hoveredSharedProject: {
+            ...sharedProject,
+            background: theme.editor.line.active.value,
+            cornerRadius: 6,
+        },
+        unsharedProject: project,
+        hoveredUnsharedProject: {
+            ...project,
+            background: theme.editor.line.active.value,
+            cornerRadius: 6,
+        },
+    }
+}

styles/styleTree/editor.ts 🔗

@@ -1,131 +1,134 @@
 import Theme from "../themes/theme";
 import {
-  backgroundColor,
-  border,
-  iconColor,
-  player,
-  text,
-  TextColor
+    backgroundColor,
+    border,
+    iconColor,
+    player,
+    text,
+    TextColor,
 } from "./components";
 
 export default function editor(theme: Theme) {
-  const autocompleteItem = {
-    cornerRadius: 6,
-    padding: {
-      bottom: 2,
-      left: 6,
-      right: 6,
-      top: 2,
-    },
-  };
-
-  function diagnostic(theme: Theme, color: TextColor) {
-    return {
-      textScaleFactor: 0.857,
-      header: {
-        border: border(theme, "primary", {
-          top: true,
-        }),
-      },
-      message: {
-        text: text(theme, "sans", color, { size: "sm" }),
-        highlightText: text(theme, "sans", color, {
-          size: "sm",
-          weight: "bold",
-        }),
-      },
+    const autocompleteItem = {
+        cornerRadius: 6,
+        padding: {
+            bottom: 2,
+            left: 6,
+            right: 6,
+            top: 2,
+        },
     };
-  }
 
-  return {
-    textColor: theme.textColor.secondary.value,
-    background: backgroundColor(theme, 300),
-    activeLineBackground: theme.editor.line.active.value,
-    codeActionsIndicator: iconColor(theme, "secondary"),
-    diffBackgroundDeleted: backgroundColor(theme, "error"),
-    diffBackgroundInserted: backgroundColor(theme, "ok"),
-    documentHighlightReadBackground: theme.editor.highlight.occurrence.value,
-    documentHighlightWriteBackground: theme.editor.highlight.occurrence.value,
-    errorColor: theme.textColor.error,
-    gutterBackground: backgroundColor(theme, 300),
-    gutterPaddingFactor: 2.5,
-    highlightedLineBackground: theme.editor.line.highlighted.value,
-    lineNumber: theme.editor.gutter.primary.value,
-    lineNumberActive: theme.editor.gutter.active,
-    renameFade: 0.6,
-    unnecessaryCodeFade: 0.5,
-    selection: player(theme, 1).selection,
-    guestSelections: [
-      player(theme, 2).selection,
-      player(theme, 3).selection,
-      player(theme, 4).selection,
-      player(theme, 5).selection,
-      player(theme, 6).selection,
-      player(theme, 7).selection,
-      player(theme, 8).selection,
-    ],
-    autocomplete: {
-      background: backgroundColor(theme, 100),
-      cornerRadius: 6,
-      padding: 6,
-      border: border(theme, "secondary"),
-      item: autocompleteItem,
-      hoveredItem: {
-        ...autocompleteItem,
-        background: backgroundColor(theme, 100, "hovered"),
-      },
-      margin: {
-        left: -14,
-      },
-      matchHighlight: {
-        color: theme.syntax.keyword.color.value,
-        weight: theme.syntax.keyword.weight.value,
-      },
-      selectedItem: {
-        ...autocompleteItem,
-        background: backgroundColor(theme, 100, "active"),
-      },
-    },
-    diagnosticHeader: {
-      background: theme.editor.background.value,
-      iconWidthFactor: 1.5,
-      textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these.
-      border: border(theme, "secondary", {
-        bottom: true,
-        top: true,
-      }),
-      code: {
-        ...text(theme, "mono", "muted", { size: "sm" }),
-        margin: {
-          left: 10,
+    function diagnostic(theme: Theme, color: TextColor) {
+        return {
+            textScaleFactor: 0.857,
+            header: {
+                border: border(theme, "primary", {
+                    top: true,
+                }),
+            },
+            message: {
+                text: text(theme, "sans", color, { size: "sm" }),
+                highlightText: text(theme, "sans", color, {
+                    size: "sm",
+                    weight: "bold",
+                }),
+            },
+        };
+    }
+
+    return {
+        textColor: theme.textColor.secondary.value,
+        background: backgroundColor(theme, 300),
+        activeLineBackground: theme.editor.line.active.value,
+        codeActionsIndicator: iconColor(theme, "secondary"),
+        diffBackgroundDeleted: backgroundColor(theme, "error"),
+        diffBackgroundInserted: backgroundColor(theme, "ok"),
+        documentHighlightReadBackground: theme.editor.highlight.occurrence.value,
+        documentHighlightWriteBackground: theme.editor.highlight.occurrence.value,
+        errorColor: theme.textColor.error.value,
+        gutterBackground: backgroundColor(theme, 300),
+        gutterPaddingFactor: 2.5,
+        highlightedLineBackground: theme.editor.line.highlighted.value,
+        lineNumber: theme.editor.gutter.primary.value,
+        lineNumberActive: theme.editor.gutter.active.value,
+        renameFade: 0.6,
+        unnecessaryCodeFade: 0.5,
+        selection: player(theme, 1).selection,
+        guestSelections: [
+            player(theme, 2).selection,
+            player(theme, 3).selection,
+            player(theme, 4).selection,
+            player(theme, 5).selection,
+            player(theme, 6).selection,
+            player(theme, 7).selection,
+            player(theme, 8).selection,
+        ],
+        autocomplete: {
+            background: backgroundColor(theme, 100),
+            cornerRadius: 6,
+            padding: 6,
+            border: border(theme, "secondary"),
+            item: autocompleteItem,
+            hoveredItem: {
+                ...autocompleteItem,
+                background: backgroundColor(theme, 100, "hovered"),
+            },
+            margin: {
+                left: -14,
+            },
+            matchHighlight: {
+                color: theme.syntax.keyword.color.value,
+                weight: theme.syntax.keyword.weight.value,
+            },
+            selectedItem: {
+                ...autocompleteItem,
+                background: backgroundColor(theme, 100, "active"),
+            },
+        },
+        diagnosticHeader: {
+            background: theme.editor.background.value,
+            iconWidthFactor: 1.5,
+            textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these.
+            border: border(theme, "secondary", {
+                bottom: true,
+                top: true,
+            }),
+            code: {
+                ...text(theme, "mono", "muted", { size: "sm" }),
+                margin: {
+                    left: 10,
+                },
+            },
+            message: {
+                highlightText: text(theme, "sans", "primary", {
+                    size: "sm",
+                    weight: "bold",
+                }),
+                text: text(theme, "sans", "secondary", { size: "sm" }),
+            },
         },
-      },
-      message: {
-        highlightText: text(theme, "sans", "primary", {
-          size: "sm",
-          weight: "bold",
-        }),
-        text: text(theme, "sans", "secondary", { size: "sm" }),
-      },
-    },
-    diagnosticPathHeader: {
-      background: theme.editor.line.active,
-      textScaleFactor: 0.857,
-      filename: text(theme, "mono", "primary", { size: "sm" }),
-      path: {
-        ...text(theme, "mono", "muted", { size: "sm" }),
-        margin: {
-          left: 12,
+        diagnosticPathHeader: {
+            background: theme.editor.line.active.value,
+            textScaleFactor: 0.857,
+            filename: text(theme, "mono", "primary", { size: "sm" }),
+            path: {
+                ...text(theme, "mono", "muted", { size: "sm" }),
+                margin: {
+                    left: 12,
+                },
+            },
         },
-      },
-    },
-    errorDiagnostic: diagnostic(theme, "error"),
-    warningDiagnostic: diagnostic(theme, "warning"),
-    informationDiagnostic: diagnostic(theme, "info"),
-    hintDiagnostic: diagnostic(theme, "info"),
-    invalidErrorDiagnostic: diagnostic(theme, "muted"),
-    invalidHintDiagnostic: diagnostic(theme, "muted"),
-    invalidInformationDiagnostic: diagnostic(theme, "muted"),
-    invalidWarningDiagnostic: diagnostic(theme, "muted"),
-  };
+        errorDiagnostic: diagnostic(theme, "error"),
+        warningDiagnostic: diagnostic(theme, "warning"),
+        informationDiagnostic: diagnostic(theme, "info"),
+        hintDiagnostic: diagnostic(theme, "info"),
+        invalidErrorDiagnostic: diagnostic(theme, "muted"),
+        invalidHintDiagnostic: diagnostic(theme, "muted"),
+        invalidInformationDiagnostic: diagnostic(theme, "muted"),
+        invalidWarningDiagnostic: diagnostic(theme, "muted"),
+        syntax: {
+
+        }
+    };
 }

styles/styleTree/projectPanel.ts 🔗

@@ -24,7 +24,11 @@ export default function projectPanel(theme: Theme) {
       backgroundColor(theme, 300, "hovered")
     ),
     selectedEntry: entry(theme, "primary"),
-    hoveredSelectedEntry: entry(theme, "primary", "hovered"),
+    hoveredSelectedEntry: entry(
+      theme, 
+      "primary", 
+      backgroundColor(theme, 300, "hovered")
+    ),
     padding: {
       top: 6,
     },

styles/styleTree/search.ts 🔗

@@ -19,8 +19,28 @@ export default function search(theme: Theme) {
     },
   };
 
+  const editor = {
+    background: backgroundColor(theme, 500),
+    cornerRadius: 6,
+    minWidth: 200,
+    maxWidth: 500,
+    placeholderText: text(theme, "mono", "placeholder"),
+    selection: player(theme, 1).selection,
+    text: text(theme, "mono", "primary"),
+    border: border(theme, "primary"),
+    margin: {
+      right: 5,
+    },
+    padding: {
+      top: 3,
+      bottom: 3,
+      left: 14,
+      right: 14,
+    },
+  };
+
   return {
-    matchBackground: theme.editor.highlight.match,
+    matchBackground: theme.editor.highlight.match.value,
     tabIconSpacing: 4,
     tabIconWidth: 14,
     activeHoveredOptionButton: {
@@ -31,31 +51,13 @@ export default function search(theme: Theme) {
       ...optionButton,
       background: backgroundColor(theme, 100),
     },
-    editor: {
-      background: backgroundColor(theme, 500),
-      cornerRadius: 6,
-      minWidth: 200,
-      maxWidth: 500,
-      placeholderText: text(theme, "mono", "placeholder"),
-      selection: player(theme, 1).selection,
-      text: text(theme, "mono", "primary"),
-      border: border(theme, "primary"),
-      margin: {
-        right: 5,
-      },
-      padding: {
-        top: 3,
-        bottom: 3,
-        left: 14,
-        right: 14,
-      },
-    },
+    editor,
     hoveredOptionButton: {
       ...optionButton,
       background: backgroundColor(theme, 100),
     },
     invalidEditor: {
-      extends: "$search.editor",
+      ...editor,
       border: border(theme, "error"),
     },
     matchIndex: {

styles/styleTree/workspace.ts 🔗

@@ -137,5 +137,10 @@ export default function workspace(theme: Theme) {
       ...text(theme, "mono", "secondary"),
       padding: { left: 6 },
     },
+    disconnectedOverlay: {
+      ...text(theme, "sans", "primary"),
+      color: "#ffffff",
+      background: "#000000aa",
+    },
   };
 }

styles/themes/dark.ts 🔗

@@ -1,249 +1,273 @@
-import core from "../tokens/core";
-import Theme, { NumberToken, Syntax } from "./theme";
-
-const { color } = core;
+import { colors, fontWeights, NumberToken } from "../tokens";
+import Theme, { Syntax } from "./theme";
 
 const backgroundColor = {
-  100: {
-    base: color.neutral[750],
-    hovered: color.neutral[750],
-    active: color.neutral[750],
-    focused: color.neutral[750],
-  },
-  300: {
-    base: color.neutral[800],
-    hovered: color.neutral[800],
-    active: color.neutral[800],
-    focused: color.neutral[800],
-  },
-  500: {
-    base: color.neutral[900],
-    hovered: color.neutral[900],
-    active: color.neutral[900],
-    focused: color.neutral[900],
-  },
-  ok: {
-    base: color.green[600],
-    hovered: color.green[600],
-    active: color.green[600],
-    focused: color.green[600],
-  },
-  error: {
-    base: color.red[400],
-    hovered: color.red[400],
-    active: color.red[400],
-    focused: color.red[400],
-  },
-  warning: {
-    base: color.amber[300],
-    hovered: color.amber[300],
-    active: color.amber[300],
-    focused: color.amber[300],
-  },
-  info: {
-    base: color.blue[500],
-    hovered: color.blue[500],
-    active: color.blue[500],
-    focused: color.blue[500],
-  },
+    100: {
+        base: colors.neutral[750],
+        hovered: colors.neutral[750],
+        active: colors.neutral[750],
+        focused: colors.neutral[750],
+    },
+    300: {
+        base: colors.neutral[800],
+        hovered: colors.neutral[800],
+        active: colors.neutral[800],
+        focused: colors.neutral[800],
+    },
+    500: {
+        base: colors.neutral[900],
+        hovered: colors.neutral[900],
+        active: colors.neutral[900],
+        focused: colors.neutral[900],
+    },
+    ok: {
+        base: colors.green[600],
+        hovered: colors.green[600],
+        active: colors.green[600],
+        focused: colors.green[600],
+    },
+    error: {
+        base: colors.red[400],
+        hovered: colors.red[400],
+        active: colors.red[400],
+        focused: colors.red[400],
+    },
+    warning: {
+        base: colors.amber[300],
+        hovered: colors.amber[300],
+        active: colors.amber[300],
+        focused: colors.amber[300],
+    },
+    info: {
+        base: colors.blue[500],
+        hovered: colors.blue[500],
+        active: colors.blue[500],
+        focused: colors.blue[500],
+    },
 };
 
 const borderColor = {
-  primary: color.neutral[850],
-  secondary: color.neutral[700],
-  muted: color.neutral[750],
-  focused: color.neutral[100],
-  active: color.neutral[500],
-  ok: color.neutral[1000],
-  error: color.neutral[1000],
-  warning: color.neutral[1000],
-  info: color.neutral[1000],
+    primary: colors.neutral[850],
+    secondary: colors.neutral[700],
+    muted: colors.neutral[750],
+    focused: colors.neutral[100],
+    active: colors.neutral[500],
+    ok: colors.neutral[1000],
+    error: colors.neutral[1000],
+    warning: colors.neutral[1000],
+    info: colors.neutral[1000],
 };
 
 const textColor = {
-  primary: color.neutral[150],
-  secondary: color.neutral[350],
-  muted: color.neutral[550],
-  placeholder: color.neutral[750],
-  active: color.neutral[0],
-  //TODO: (design) define feature and it's correct value
-  feature: color.sky[500],
-  ok: color.green[600],
-  error: color.red[400],
-  warning: color.amber[300],
-  info: color.blue[500],
+    primary: colors.neutral[150],
+    secondary: colors.neutral[350],
+    muted: colors.neutral[550],
+    placeholder: colors.neutral[750],
+    active: colors.neutral[0],
+    //TODO: (design) define feature and it's correct value
+    feature: colors.sky[500],
+    ok: colors.green[600],
+    error: colors.red[400],
+    warning: colors.amber[300],
+    info: colors.blue[500],
 };
 
 const iconColor = {
-  primary: color.neutral[300],
-  secondary: color.neutral[500],
-  muted: color.neutral[600],
-  placeholder: color.neutral[700],
-  active: color.neutral[50],
-  //TODO: (design) define feature and it's correct value
-  feature: color.sky[500],
-  ok: color.green[600],
-  error: color.red[400],
-  warning: color.amber[300],
-  info: color.blue[500],
+    primary: colors.neutral[300],
+    secondary: colors.neutral[500],
+    muted: colors.neutral[600],
+    placeholder: colors.neutral[700],
+    active: colors.neutral[50],
+    //TODO: (design) define feature and it's correct value
+    feature: colors.sky[500],
+    ok: colors.green[600],
+    error: colors.red[400],
+    warning: colors.amber[300],
+    info: colors.blue[500],
 };
 
 const player = {
-  1: {
-    baseColor: color.blue[600],
-    cursorColor: color.blue[600],
-    selectionColor: color.blue[600],
-    borderColor: color.blue[600],
-  },
-  2: {
-    baseColor: color.indigo[500],
-    cursorColor: color.indigo[500],
-    selectionColor: color.indigo[500],
-    borderColor: color.indigo[500],
-  },
-  3: {
-    baseColor: color.green[500],
-    cursorColor: color.green[500],
-    selectionColor: color.green[500],
-    borderColor: color.green[500],
-  },
-  4: {
-    baseColor: color.orange[500],
-    cursorColor: color.orange[500],
-    selectionColor: color.orange[500],
-    borderColor: color.orange[500],
-  },
-  5: {
-    baseColor: color.purple[500],
-    cursorColor: color.purple[500],
-    selectionColor: color.purple[500],
-    borderColor: color.purple[500],
-  },
-  6: {
-    baseColor: color.teal[400],
-    cursorColor: color.teal[400],
-    selectionColor: color.teal[400],
-    borderColor: color.teal[400],
-  },
-  7: {
-    baseColor: color.pink[400],
-    cursorColor: color.pink[400],
-    selectionColor: color.pink[400],
-    borderColor: color.pink[400],
-  },
-  8: {
-    baseColor: color.yellow[400],
-    cursorColor: color.yellow[400],
-    selectionColor: color.yellow[400],
-    borderColor: color.yellow[400],
-  },
+    1: {
+        baseColor: colors.blue[600],
+        cursorColor: colors.blue[600],
+        selectionColor: colors.blue[600],
+        borderColor: colors.blue[600],
+    },
+    2: {
+        baseColor: colors.indigo[500],
+        cursorColor: colors.indigo[500],
+        selectionColor: colors.indigo[500],
+        borderColor: colors.indigo[500],
+    },
+    3: {
+        baseColor: colors.green[500],
+        cursorColor: colors.green[500],
+        selectionColor: colors.green[500],
+        borderColor: colors.green[500],
+    },
+    4: {
+        baseColor: colors.orange[500],
+        cursorColor: colors.orange[500],
+        selectionColor: colors.orange[500],
+        borderColor: colors.orange[500],
+    },
+    5: {
+        baseColor: colors.purple[500],
+        cursorColor: colors.purple[500],
+        selectionColor: colors.purple[500],
+        borderColor: colors.purple[500],
+    },
+    6: {
+        baseColor: colors.teal[400],
+        cursorColor: colors.teal[400],
+        selectionColor: colors.teal[400],
+        borderColor: colors.teal[400],
+    },
+    7: {
+        baseColor: colors.pink[400],
+        cursorColor: colors.pink[400],
+        selectionColor: colors.pink[400],
+        borderColor: colors.pink[400],
+    },
+    8: {
+        baseColor: colors.yellow[400],
+        cursorColor: colors.yellow[400],
+        selectionColor: colors.yellow[400],
+        borderColor: colors.yellow[400],
+    },
 };
 
 // TODO: Fixup
 const editor = {
-  background: backgroundColor[500].base,
-  indent_guide: borderColor.muted,
-  indent_guide_active: borderColor.secondary,
-  line: {
-    active: color.neutral[0],
-    highlighted: color.neutral[0],
-    inserted: backgroundColor.ok.active,
-    deleted: backgroundColor.error.active,
-    modified: backgroundColor.info.active,
-  },
-  highlight: {
-    selection: player[1].selectionColor,
-    occurrence: backgroundColor[500].active,
-    activeOccurrence: color.neutral[0],
-    matchingBracket: color.neutral[0],
-    match: color.neutral[0],
-    activeMatch: color.neutral[0],
-    related: color.neutral[0],
-  },
-  gutter: {
-    primary: color.neutral[0],
-    active: color.neutral[0],
-  },
+    background: backgroundColor[500].base,
+    indent_guide: borderColor.muted,
+    indent_guide_active: borderColor.secondary,
+    line: {
+        active: colors.neutral[0],
+        highlighted: colors.neutral[0],
+        inserted: backgroundColor.ok.active,
+        deleted: backgroundColor.error.active,
+        modified: backgroundColor.info.active,
+    },
+    highlight: {
+        selection: player[1].selectionColor,
+        occurrence: backgroundColor[500].active,
+        activeOccurrence: colors.neutral[0],
+        matchingBracket: colors.neutral[0],
+        match: colors.neutral[0],
+        activeMatch: colors.neutral[0],
+        related: colors.neutral[0],
+    },
+    gutter: {
+        primary: colors.neutral[0],
+        active: colors.neutral[0],
+    },
 };
 
 const syntax: Syntax = {
-  primary: {
-    color: textColor.primary,
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  comment: {
-    color: color.lime[200],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  punctuation: {
-    color: textColor.primary,
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  constant: {
-    color: color.neutral[150],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  keyword: {
-    color: color.sky[400],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  function: {
-    color: color.yellow[200],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  type: {
-    color: color.teal[300],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  variant: {
-    color: color.teal[300],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  property: {
-    color: color.sky[300],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  enum: {
-    color: color.sky[400],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  operator: {
-    color: color.sky[400],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  string: {
-    color: color.orange[300],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  number: {
-    color: color.neutral[150],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  boolean: {
-    color: color.neutral[150],
-    weight: { value: "normal", type: "fontWeight" },
-  },
-  predictive: {
-    color: textColor.muted,
-    weight: { value: "normal", type: "fontWeight" },
-  },
+    primary: {
+        color: textColor.primary,
+        weight: fontWeights.normal,
+    },
+    comment: {
+        color: colors.lime[200],
+        weight: fontWeights.normal,
+    },
+    punctuation: {
+        color: textColor.primary,
+        weight: fontWeights.normal,
+    },
+    constant: {
+        color: colors.neutral[150],
+        weight: fontWeights.normal,
+    },
+    keyword: {
+        color: colors.sky[400],
+        weight: fontWeights.normal,
+    },
+    function: {
+        color: colors.yellow[200],
+        weight: fontWeights.normal,
+    },
+    type: {
+        color: colors.teal[300],
+        weight: fontWeights.normal,
+    },
+    variant: {
+        color: colors.teal[300],
+        weight: fontWeights.normal,
+    },
+    property: {
+        color: colors.sky[300],
+        weight: fontWeights.normal,
+    },
+    enum: {
+        color: colors.sky[400],
+        weight: fontWeights.normal,
+    },
+    operator: {
+        color: colors.sky[400],
+        weight: fontWeights.normal,
+    },
+    string: {
+        color: colors.orange[300],
+        weight: fontWeights.normal,
+    },
+    number: {
+        color: colors.neutral[150],
+        weight: fontWeights.normal,
+    },
+    boolean: {
+        color: colors.neutral[150],
+        weight: fontWeights.normal,
+    },
+    predictive: {
+        color: textColor.muted,
+        weight: fontWeights.normal,
+    },
+    title: {
+        color: colors.sky[500],
+        weight: fontWeights.bold,
+    },
+    emphasis: {
+        color: textColor.active,
+        weight: fontWeights.normal,
+    },
+    emphasisStrong: {
+        color: textColor.active,
+        weight: fontWeights.bold,
+    },
+    linkUrl: {
+        color: colors.lime[500],
+        weight: fontWeights.normal,
+        // TODO: add underline
+    },
+    linkText: {
+        color: colors.orange[500],
+        weight: fontWeights.normal,
+        // TODO: add italic
+    },
+    listMarker: {
+        color: colors.sky[400],
+        weight: fontWeights.normal,
+    }
 };
 
 const shadowAlpha: NumberToken = {
-  value: 0.32,
-  type: "number",
+    value: 0.32,
+    type: "number",
 };
 
 const theme: Theme = {
-  name: "dark",
-  backgroundColor,
-  borderColor,
-  textColor,
-  iconColor,
-  editor,
-  syntax,
-  player,
-  shadowAlpha,
+    name: "dark",
+    backgroundColor,
+    borderColor,
+    textColor,
+    iconColor,
+    editor,
+    syntax,
+    player,
+    shadowAlpha,
 };
 
 export default theme;

styles/themes/light.ts 🔗

@@ -1,143 +1,141 @@
-import core from "../tokens/core";
-import Theme, { NumberToken, Syntax } from "./theme";
-
-const { color } = core;
+import { colors, fontWeights, NumberToken } from "../tokens";
+import Theme, { Syntax } from "./theme";
 
 // TODO: Replace with light values
 
 const backgroundColor = {
   100: {
-    base: color.neutral[750],
-    hovered: color.neutral[750],
-    active: color.neutral[750],
-    focused: color.neutral[750],
+      base: colors.neutral[750],
+      hovered: colors.neutral[750],
+      active: colors.neutral[750],
+      focused: colors.neutral[750],
   },
   300: {
-    base: color.neutral[800],
-    hovered: color.neutral[800],
-    active: color.neutral[800],
-    focused: color.neutral[800],
+      base: colors.neutral[800],
+      hovered: colors.neutral[800],
+      active: colors.neutral[800],
+      focused: colors.neutral[800],
   },
   500: {
-    base: color.neutral[900],
-    hovered: color.neutral[900],
-    active: color.neutral[900],
-    focused: color.neutral[900],
+      base: colors.neutral[900],
+      hovered: colors.neutral[900],
+      active: colors.neutral[900],
+      focused: colors.neutral[900],
   },
   ok: {
-    base: color.green[600],
-    hovered: color.green[600],
-    active: color.green[600],
-    focused: color.green[600],
+      base: colors.green[600],
+      hovered: colors.green[600],
+      active: colors.green[600],
+      focused: colors.green[600],
   },
   error: {
-    base: color.red[400],
-    hovered: color.red[400],
-    active: color.red[400],
-    focused: color.red[400],
+      base: colors.red[400],
+      hovered: colors.red[400],
+      active: colors.red[400],
+      focused: colors.red[400],
   },
   warning: {
-    base: color.amber[300],
-    hovered: color.amber[300],
-    active: color.amber[300],
-    focused: color.amber[300],
+      base: colors.amber[300],
+      hovered: colors.amber[300],
+      active: colors.amber[300],
+      focused: colors.amber[300],
   },
   info: {
-    base: color.blue[500],
-    hovered: color.blue[500],
-    active: color.blue[500],
-    focused: color.blue[500],
+      base: colors.blue[500],
+      hovered: colors.blue[500],
+      active: colors.blue[500],
+      focused: colors.blue[500],
   },
 };
 
 const borderColor = {
-  primary: color.neutral[850],
-  secondary: color.neutral[700],
-  muted: color.neutral[750],
-  focused: color.neutral[100],
-  active: color.neutral[500],
-  ok: color.neutral[1000],
-  error: color.neutral[1000],
-  warning: color.neutral[1000],
-  info: color.neutral[1000],
+  primary: colors.neutral[850],
+  secondary: colors.neutral[700],
+  muted: colors.neutral[750],
+  focused: colors.neutral[100],
+  active: colors.neutral[500],
+  ok: colors.neutral[1000],
+  error: colors.neutral[1000],
+  warning: colors.neutral[1000],
+  info: colors.neutral[1000],
 };
 
 const textColor = {
-  primary: color.neutral[150],
-  secondary: color.neutral[350],
-  muted: color.neutral[550],
-  placeholder: color.neutral[750],
-  active: color.neutral[0],
+  primary: colors.neutral[150],
+  secondary: colors.neutral[350],
+  muted: colors.neutral[550],
+  placeholder: colors.neutral[750],
+  active: colors.neutral[0],
   //TODO: (design) define feature and it's correct value
-  feature: color.sky[500],
-  ok: color.green[600],
-  error: color.red[400],
-  warning: color.amber[300],
-  info: color.blue[500],
+  feature: colors.sky[500],
+  ok: colors.green[600],
+  error: colors.red[400],
+  warning: colors.amber[300],
+  info: colors.blue[500],
 };
 
 const iconColor = {
-  primary: color.neutral[300],
-  secondary: color.neutral[500],
-  muted: color.neutral[600],
-  placeholder: color.neutral[700],
-  active: color.neutral[50],
+  primary: colors.neutral[300],
+  secondary: colors.neutral[500],
+  muted: colors.neutral[600],
+  placeholder: colors.neutral[700],
+  active: colors.neutral[50],
   //TODO: (design) define feature and it's correct value
-  feature: color.sky[500],
-  ok: color.green[600],
-  error: color.red[400],
-  warning: color.amber[300],
-  info: color.blue[500],
+  feature: colors.sky[500],
+  ok: colors.green[600],
+  error: colors.red[400],
+  warning: colors.amber[300],
+  info: colors.blue[500],
 };
 
 const player = {
   1: {
-    baseColor: color.blue[600],
-    cursorColor: color.blue[600],
-    selectionColor: color.blue[600],
-    borderColor: color.blue[600],
+      baseColor: colors.blue[600],
+      cursorColor: colors.blue[600],
+      selectionColor: colors.blue[600],
+      borderColor: colors.blue[600],
   },
   2: {
-    baseColor: color.indigo[500],
-    cursorColor: color.indigo[500],
-    selectionColor: color.indigo[500],
-    borderColor: color.indigo[500],
+      baseColor: colors.indigo[500],
+      cursorColor: colors.indigo[500],
+      selectionColor: colors.indigo[500],
+      borderColor: colors.indigo[500],
   },
   3: {
-    baseColor: color.green[500],
-    cursorColor: color.green[500],
-    selectionColor: color.green[500],
-    borderColor: color.green[500],
+      baseColor: colors.green[500],
+      cursorColor: colors.green[500],
+      selectionColor: colors.green[500],
+      borderColor: colors.green[500],
   },
   4: {
-    baseColor: color.orange[500],
-    cursorColor: color.orange[500],
-    selectionColor: color.orange[500],
-    borderColor: color.orange[500],
+      baseColor: colors.orange[500],
+      cursorColor: colors.orange[500],
+      selectionColor: colors.orange[500],
+      borderColor: colors.orange[500],
   },
   5: {
-    baseColor: color.purple[500],
-    cursorColor: color.purple[500],
-    selectionColor: color.purple[500],
-    borderColor: color.purple[500],
+      baseColor: colors.purple[500],
+      cursorColor: colors.purple[500],
+      selectionColor: colors.purple[500],
+      borderColor: colors.purple[500],
   },
   6: {
-    baseColor: color.teal[400],
-    cursorColor: color.teal[400],
-    selectionColor: color.teal[400],
-    borderColor: color.teal[400],
+      baseColor: colors.teal[400],
+      cursorColor: colors.teal[400],
+      selectionColor: colors.teal[400],
+      borderColor: colors.teal[400],
   },
   7: {
-    baseColor: color.pink[400],
-    cursorColor: color.pink[400],
-    selectionColor: color.pink[400],
-    borderColor: color.pink[400],
+      baseColor: colors.pink[400],
+      cursorColor: colors.pink[400],
+      selectionColor: colors.pink[400],
+      borderColor: colors.pink[400],
   },
   8: {
-    baseColor: color.yellow[400],
-    cursorColor: color.yellow[400],
-    selectionColor: color.yellow[400],
-    borderColor: color.yellow[400],
+      baseColor: colors.yellow[400],
+      cursorColor: colors.yellow[400],
+      selectionColor: colors.yellow[400],
+      borderColor: colors.yellow[400],
   },
 };
 
@@ -147,88 +145,114 @@ const editor = {
   indent_guide: borderColor.muted,
   indent_guide_active: borderColor.secondary,
   line: {
-    active: color.neutral[0],
-    highlighted: color.neutral[0],
-    inserted: backgroundColor.ok.active,
-    deleted: backgroundColor.error.active,
-    modified: backgroundColor.info.active,
+      active: colors.neutral[0],
+      highlighted: colors.neutral[0],
+      inserted: backgroundColor.ok.active,
+      deleted: backgroundColor.error.active,
+      modified: backgroundColor.info.active,
   },
   highlight: {
-    selection: player[1].selectionColor,
-    occurrence: backgroundColor[500].active,
-    activeOccurrence: color.neutral[0],
-    matchingBracket: color.neutral[0],
-    match: color.neutral[0],
-    activeMatch: color.neutral[0],
-    related: color.neutral[0],
+      selection: player[1].selectionColor,
+      occurrence: backgroundColor[500].active,
+      activeOccurrence: colors.neutral[0],
+      matchingBracket: colors.neutral[0],
+      match: colors.neutral[0],
+      activeMatch: colors.neutral[0],
+      related: colors.neutral[0],
   },
   gutter: {
-    primary: color.neutral[0],
-    active: color.neutral[0],
+      primary: colors.neutral[0],
+      active: colors.neutral[0],
   },
 };
 
 const syntax: Syntax = {
   primary: {
-    color: textColor.primary,
-    weight: { value: "normal", type: "fontWeight" },
+      color: textColor.primary,
+      weight: fontWeights.normal,
   },
   comment: {
-    color: color.lime[200],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.lime[200],
+      weight: fontWeights.normal,
   },
   punctuation: {
-    color: textColor.primary,
-    weight: { value: "normal", type: "fontWeight" },
+      color: textColor.primary,
+      weight: fontWeights.normal,
   },
   constant: {
-    color: color.neutral[150],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.neutral[150],
+      weight: fontWeights.normal,
   },
   keyword: {
-    color: color.sky[400],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.sky[400],
+      weight: fontWeights.normal,
   },
   function: {
-    color: color.yellow[200],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.yellow[200],
+      weight: fontWeights.normal,
   },
   type: {
-    color: color.teal[300],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.teal[300],
+      weight: fontWeights.normal,
   },
   variant: {
-    color: color.teal[300],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.teal[300],
+      weight: fontWeights.normal,
   },
   property: {
-    color: color.sky[300],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.sky[300],
+      weight: fontWeights.normal,
   },
   enum: {
-    color: color.sky[400],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.sky[400],
+      weight: fontWeights.normal,
   },
   operator: {
-    color: color.sky[400],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.sky[400],
+      weight: fontWeights.normal,
   },
   string: {
-    color: color.orange[300],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.orange[300],
+      weight: fontWeights.normal,
   },
   number: {
-    color: color.neutral[150],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.neutral[150],
+      weight: fontWeights.normal,
   },
   boolean: {
-    color: color.neutral[150],
-    weight: { value: "normal", type: "fontWeight" },
+      color: colors.neutral[150],
+      weight: fontWeights.normal,
   },
   predictive: {
-    color: textColor.muted,
-    weight: { value: "normal", type: "fontWeight" },
-  },
+      color: textColor.muted,
+      weight: fontWeights.normal,
+  },
+  title: {
+      color: colors.sky[500],
+      weight: fontWeights.bold,
+  },
+  emphasis: {
+      color: textColor.active,
+      weight: fontWeights.normal,
+  },
+  emphasisStrong: {
+      color: textColor.active,
+      weight: fontWeights.bold,
+  },
+  linkUrl: {
+      color: colors.lime[500],
+      weight: fontWeights.normal,
+      // TODO: add underline
+  },
+  linkText: {
+      color: colors.orange[500],
+      weight: fontWeights.normal,
+      // TODO: add italic
+  },
+  listMarker: {
+      color: colors.sky[400],
+      weight: fontWeights.normal,
+  }
 };
 
 const shadowAlpha: NumberToken = {

styles/themes/theme.ts 🔗

@@ -1,32 +1,8 @@
-export interface NumberToken {
-    value: number,
-    type: "number"
-}
-
-export type Color = string;
-export interface ColorToken {
-    value: Color;
-    type: "color";
-    step?: number
-}
-export type Weight =
-    | "thin"
-    | "extra_light"
-    | "light"
-    | "normal"
-    | "medium"
-    | "semibold"
-    | "bold"
-    | "extra_bold"
-    | "black";
-export interface WeightToken {
-    value: Weight,
-    type: "fontWeight"
-}
+import { FontWeightToken, ColorToken, NumberToken } from "../tokens";
 
 export interface SyntaxHighlightStyle {
     color: ColorToken;
-    weight: WeightToken;
+    weight: FontWeightToken;
 }
 
 export interface Player {
@@ -43,7 +19,7 @@ export interface BackgroundColor {
     focused: ColorToken;
 }
 
-export interface Syntax { 
+export interface Syntax {
     primary: SyntaxHighlightStyle;
     comment: SyntaxHighlightStyle;
     punctuation: SyntaxHighlightStyle;
@@ -59,6 +35,13 @@ export interface Syntax {
     number: SyntaxHighlightStyle;
     boolean: SyntaxHighlightStyle;
     predictive: SyntaxHighlightStyle;
+    // TODO: Either move the following or rename
+    title: SyntaxHighlightStyle;
+    emphasis: SyntaxHighlightStyle;
+    emphasisStrong: SyntaxHighlightStyle;
+    linkUrl: SyntaxHighlightStyle;
+    linkText: SyntaxHighlightStyle;
+    listMarker: SyntaxHighlightStyle;
 };
 
 export default interface Theme {

styles/tokens.ts 🔗

@@ -0,0 +1,102 @@
+import { colorRamp } from "./utils/color";
+
+interface Token<V, T> {
+  value: V,
+  type: T
+}
+
+export type FontFamily = string;
+export type FontFamilyToken = Token<FontFamily, "fontFamily">;
+function fontFamily(value: FontFamily): FontFamilyToken {
+  return {
+    value,
+    type: "fontFamily"
+  }
+}
+export const fontFamilies = {
+  sans: fontFamily("Zed Sans"),
+  mono: fontFamily("Zed Mono"),
+}
+
+export type FontSize = number;
+export type FontSizeToken = Token<FontSize, "fontSize">;
+function fontSize(value: FontSize) {
+  return {
+    value,
+    type: "fontSize"
+  };
+}
+export const fontSizes = {
+  "3xs": fontSize(8),
+  "2xs": fontSize(10),
+  xs: fontSize(12),
+  sm: fontSize(14),
+  md: fontSize(16),
+  lg: fontSize(18),
+  xl: fontSize(20),
+};
+
+export type FontWeight = 
+  | "thin"
+  | "extra_light"
+  | "light"
+  | "normal"
+  | "medium"
+  | "semibold"
+  | "bold"
+  | "extra_bold"
+  | "black";
+export type FontWeightToken = Token<FontWeight, "fontWeight">;
+function fontWeight(value: FontWeight): FontWeightToken {
+  return {
+    value,
+    type: "fontWeight"
+  };
+}
+export const fontWeights = {
+  "thin": fontWeight("thin"),
+  "extra_light": fontWeight("extra_light"),
+  "light": fontWeight("light"),
+  "normal": fontWeight("normal"),
+  "medium": fontWeight("medium"),
+  "semibold": fontWeight("semibold"),
+  "bold": fontWeight("bold"),
+  "extra_bold": fontWeight("extra_bold"),
+  "black": fontWeight("black"),
+}
+
+export type Color = string;
+export interface ColorToken {
+  value: Color,
+  type: "color",
+  step?: number,
+}
+export const colors = {
+  neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }),
+  rose: colorRamp("#F43F5EFF"),
+  red: colorRamp("#EF4444FF"),
+  orange: colorRamp("#F97316FF"),
+  amber: colorRamp("#F59E0BFF"),
+  yellow: colorRamp("#EAB308FF"),
+  lime: colorRamp("#84CC16FF"),
+  green: colorRamp("#22C55EFF"),
+  emerald: colorRamp("#10B981FF"),
+  teal: colorRamp("#14B8A6FF"),
+  cyan: colorRamp("#06BBD4FF"),
+  sky: colorRamp("#0EA5E9FF"),
+  blue: colorRamp("#3B82F6FF"),
+  indigo: colorRamp("#6366F1FF"),
+  violet: colorRamp("#8B5CF6FF"),
+  purple: colorRamp("#A855F7FF"),
+  fuschia: colorRamp("#D946E4FF"),
+  pink: colorRamp("#EC4899FF"),
+}
+
+export type NumberToken = Token<number, "number">;
+
+export default {
+  fontFamilies,
+  fontSizes,
+  fontWeights,
+  colors,
+};

styles/tokens/core.ts 🔗

@@ -1,58 +0,0 @@
-import { colorRamp } from "../utils/color";
-
-export default {
-    fontFamily: {
-        sans: "Zed Sans",
-        mono: "Zed Mono",
-    },
-    fontSize: {
-        "3xs": {
-            value: "8",
-            type: "fontSizes",
-        },
-        "2xs": {
-            value: "10",
-            type: "fontSizes",
-        },
-        xs: {
-            value: "12",
-            type: "fontSizes",
-        },
-        sm: {
-            value: "14",
-            type: "fontSizes",
-        },
-        md: {
-            value: "16",
-            type: "fontSizes",
-        },
-        lg: {
-            value: "18",
-            type: "fontSizes",
-        },
-        xl: {
-            value: "20",
-            type: "fontSizes",
-        },
-    },
-    color: {
-        neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }),
-        rose: colorRamp("#F43F5EFF"),
-        red: colorRamp("#EF4444FF"),
-        orange: colorRamp("#F97316FF"),
-        amber: colorRamp("#F59E0BFF"),
-        yellow: colorRamp("#EAB308FF"),
-        lime: colorRamp("#84CC16FF"),
-        green: colorRamp("#22C55EFF"),
-        emerald: colorRamp("#10B981FF"),
-        teal: colorRamp("#14B8A6FF"),
-        cyan: colorRamp("#06BBD4FF"),
-        sky: colorRamp("#0EA5E9FF"),
-        blue: colorRamp("#3B82F6FF"),
-        indigo: colorRamp("#6366F1FF"),
-        violet: colorRamp("#8B5CF6FF"),
-        purple: colorRamp("#A855F7FF"),
-        fuschia: colorRamp("#D946E4FF"),
-        pink: colorRamp("#EC4899FF"),
-    },
-};