`theme` crate spring cleaning (#18695)

Nate Butler and Marshall Bowers created

This PR does some spring cleaning on the `theme` crate:

- Removed two unused stories and the story dep
- Removed the `one` theme family (from the `theme` crate, not the app),
this is now `zed_default_themes`.
- This will hopefully remove some confusion caused by this theme we
started in rust but didn't end up using
- Removed `theme::prelude` (it just re-exported scale colors, which we
don't use outside `theme`)
- Removed completely unused `zed_pro` themes (we started on these during
the gpui2 port and didn't finish them.)

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>

Change summary

Cargo.lock                                 |   1 
crates/theme/Cargo.toml                    |   2 
crates/theme/src/default_theme.rs          |  71 -----------
crates/theme/src/fallback_themes.rs        |  18 +-
crates/theme/src/prelude.rs                |   6 -
crates/theme/src/registry.rs               |   9 -
crates/theme/src/settings.rs               |   4 
crates/theme/src/styles.rs                 |   6 -
crates/theme/src/styles/stories/color.rs   |  40 ------
crates/theme/src/styles/stories/mod.rs     |   5 
crates/theme/src/styles/stories/players.rs | 143 ------------------------
crates/theme/src/theme.rs                  |   8 -
crates/theme/theme.md                      |  15 --
crates/theme/util/hex_to_hsla.py           |  35 -----
14 files changed, 15 insertions(+), 348 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -11655,7 +11655,6 @@ dependencies = [
  "serde_json_lenient",
  "serde_repr",
  "settings",
- "story",
  "util",
  "uuid",
 ]

crates/theme/Cargo.toml 🔗

@@ -10,7 +10,6 @@ workspace = true
 
 [features]
 default = []
-stories = ["dep:story"]
 test-support = ["gpui/test-support", "fs/test-support", "settings/test-support"]
 
 [lib]
@@ -36,7 +35,6 @@ serde_json.workspace = true
 serde_json_lenient.workspace = true
 serde_repr.workspace = true
 settings.workspace = true
-story = { workspace = true, optional = true }
 util.workspace = true
 uuid.workspace = true
 

crates/theme/src/default_theme.rs 🔗

@@ -1,71 +0,0 @@
-use std::sync::Arc;
-
-use gpui::WindowBackgroundAppearance;
-
-use crate::AccentColors;
-
-use crate::{
-    default_color_scales,
-    one_themes::{one_dark, one_family},
-    Appearance, PlayerColors, StatusColors, SyntaxTheme, SystemColors, Theme, ThemeColors,
-    ThemeFamily, ThemeStyles,
-};
-
-fn zed_pro_daylight() -> Theme {
-    Theme {
-        id: "zed_pro_daylight".to_string(),
-        name: "Zed Pro Daylight".into(),
-        appearance: Appearance::Light,
-        styles: ThemeStyles {
-            window_background_appearance: WindowBackgroundAppearance::Opaque,
-            system: SystemColors::default(),
-            colors: ThemeColors::light(),
-            status: StatusColors::light(),
-            player: PlayerColors::light(),
-            syntax: Arc::new(SyntaxTheme::default()),
-            accents: AccentColors::light(),
-        },
-    }
-}
-
-pub(crate) fn zed_pro_moonlight() -> Theme {
-    Theme {
-        id: "zed_pro_moonlight".to_string(),
-        name: "Zed Pro Moonlight".into(),
-        appearance: Appearance::Dark,
-        styles: ThemeStyles {
-            window_background_appearance: WindowBackgroundAppearance::Opaque,
-            system: SystemColors::default(),
-            colors: ThemeColors::dark(),
-            status: StatusColors::dark(),
-            player: PlayerColors::dark(),
-            syntax: Arc::new(SyntaxTheme::default()),
-            accents: AccentColors::dark(),
-        },
-    }
-}
-
-/// Returns the Zed Pro theme family.
-///
-/// Note: To be removed until the theme is implemented.
-pub fn zed_pro_family() -> ThemeFamily {
-    ThemeFamily {
-        id: "zed_pro".to_string(),
-        name: "Zed Pro".into(),
-        author: "Zed Team".into(),
-        themes: vec![zed_pro_daylight(), zed_pro_moonlight()],
-        scales: default_color_scales(),
-    }
-}
-
-impl Default for ThemeFamily {
-    fn default() -> Self {
-        one_family()
-    }
-}
-
-impl Default for Theme {
-    fn default() -> Self {
-        one_dark()
-    }
-}

crates/theme/src/one_themes.rs → crates/theme/src/fallback_themes.rs 🔗

@@ -7,21 +7,21 @@ use crate::{
     SystemColors, Theme, ThemeColors, ThemeFamily, ThemeStyles,
 };
 
-// Note: This theme family is not the one you see in Zed at the moment.
-// This is a from-scratch rebuild that Nate started work on. We currently
-// only use this in the tests, and the One family from the `themes/` directory
-// is what gets loaded into Zed when running it.
-pub fn one_family() -> ThemeFamily {
+/// The default theme family for Zed.
+///
+/// This is used to construct the default theme fallback values, as well as to
+/// have a theme available at compile time for tests.
+pub fn zed_default_themes() -> ThemeFamily {
     ThemeFamily {
-        id: "one".to_string(),
-        name: "One".into(),
+        id: "zed-default".to_string(),
+        name: "Zed Default".into(),
         author: "".into(),
-        themes: vec![one_dark()],
+        themes: vec![zed_default_dark()],
         scales: default_color_scales(),
     }
 }
 
-pub(crate) fn one_dark() -> Theme {
+pub(crate) fn zed_default_dark() -> Theme {
     let bg = hsla(215. / 360., 12. / 100., 15. / 100., 1.);
     let editor = hsla(220. / 360., 12. / 100., 18. / 100., 1.);
     let elevated_surface = hsla(225. / 360., 12. / 100., 17. / 100., 1.);

crates/theme/src/prelude.rs 🔗

@@ -1,6 +0,0 @@
-#[allow(unused)]
-pub(crate) use crate::default_colors::{
-    amber, black, blue, bronze, brown, crimson, cyan, gold, grass, gray, green, indigo, iris, jade,
-    lime, mauve, mint, olive, orange, pink, plum, purple, red, ruby, sage, sand, sky, slate, teal,
-    tomato, violet, white, yellow,
-};

crates/theme/src/registry.rs 🔗

@@ -74,12 +74,9 @@ impl ThemeRegistry {
             assets,
         };
 
-        // We're loading our new versions of the One themes by default, as
-        // we need them to be loaded for tests.
-        //
-        // These themes will get overwritten when `load_user_themes` is called
-        // when Zed starts, so the One variants used will be the ones ported from Zed1.
-        registry.insert_theme_families([crate::one_themes::one_family()]);
+        // We're loading the Zed default theme, as we need a theme to be loaded
+        // for tests.
+        registry.insert_theme_families([crate::fallback_themes::zed_default_themes()]);
 
         registry
     }

crates/theme/src/settings.rs 🔗

@@ -1,4 +1,4 @@
-use crate::one_themes::one_dark;
+use crate::fallback_themes::zed_default_dark;
 use crate::{Appearance, SyntaxTheme, Theme, ThemeRegistry, ThemeStyleContent};
 use anyhow::Result;
 use derive_more::{Deref, DerefMut};
@@ -629,7 +629,7 @@ impl settings::Settings for ThemeSettings {
             theme_selection: defaults.theme.clone(),
             active_theme: themes
                 .get(defaults.theme.as_ref().unwrap().theme(*system_appearance))
-                .or(themes.get(&one_dark().name))
+                .or(themes.get(&zed_default_dark().name))
                 .unwrap(),
             theme_overrides: None,
             ui_density: defaults.ui_density.unwrap_or(UiDensity::Default),

crates/theme/src/styles.rs 🔗

@@ -5,15 +5,9 @@ mod status;
 mod syntax;
 mod system;
 
-#[cfg(feature = "stories")]
-mod stories;
-
 pub use accents::*;
 pub use colors::*;
 pub use players::*;
 pub use status::*;
 pub use syntax::*;
 pub use system::*;
-
-#[cfg(feature = "stories")]
-pub use stories::*;

crates/theme/src/styles/stories/color.rs 🔗

@@ -1,40 +0,0 @@
-use gpui::prelude::*;
-use gpui::{div, px, ViewContext};
-use story::Story;
-
-use crate::{default_color_scales, ColorScaleStep};
-
-/// The story showcasing all the default color scales
-pub struct ColorsStory;
-
-impl Render for ColorsStory {
-    fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
-        let color_scales = default_color_scales();
-
-        Story::container().child(Story::title("Colors")).child(
-            div()
-                .id("colors")
-                .flex()
-                .flex_col()
-                .gap_1()
-                .overflow_y_scroll()
-                .text_color(gpui::white())
-                .children(color_scales.into_iter().map(|scale| {
-                    div()
-                        .flex()
-                        .child(
-                            div()
-                                .w(px(75.))
-                                .line_height(px(24.))
-                                .child(scale.name().clone()),
-                        )
-                        .child(
-                            div().flex().gap_1().children(
-                                ColorScaleStep::ALL
-                                    .map(|step| div().flex().size_6().bg(scale.step(cx, step))),
-                            ),
-                        )
-                })),
-        )
-    }
-}

crates/theme/src/styles/stories/players.rs 🔗

@@ -1,143 +0,0 @@
-use gpui::{div, img, px, IntoElement, ParentElement, Render, Styled, ViewContext};
-use story::Story;
-
-use crate::{ActiveTheme, PlayerColors};
-
-/// The story showcasing the player colors
-pub struct PlayerStory;
-
-impl Render for PlayerStory {
-    fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
-        Story::container().child(
-            div()
-                .flex()
-                .flex_col()
-                .gap_4()
-                .child(Story::title_for::<PlayerColors>())
-                .child(Story::label("Player Colors"))
-                .child(
-                    div()
-                        .flex()
-                        .flex_col()
-                        .gap_1()
-                        .child(
-                            div().flex().gap_1().children(
-                                cx.theme()
-                                    .players()
-                                    .0
-                                    .clone()
-                                    .iter_mut()
-                                    .map(|player| div().w_8().h_8().rounded_md().bg(player.cursor)),
-                            ),
-                        )
-                        .child(
-                            div().flex().gap_1().children(
-                                cx.theme().players().0.clone().iter_mut().map(|player| {
-                                    div().w_8().h_8().rounded_md().bg(player.background)
-                                }),
-                            ),
-                        )
-                        .child(
-                            div().flex().gap_1().children(
-                                cx.theme().players().0.clone().iter_mut().map(|player| {
-                                    div().w_8().h_8().rounded_md().bg(player.selection)
-                                }),
-                            ),
-                        ),
-                )
-                .child(Story::label("Avatar Rings"))
-                .child(div().flex().gap_1().children(
-                    cx.theme().players().0.clone().iter_mut().map(|player| {
-                        div()
-                            .my_1()
-                            .rounded_full()
-                            .border_2()
-                            .border_color(player.cursor)
-                            .child(
-                                img("https://avatars.githubusercontent.com/u/1714999?v=4")
-                                    .rounded_full()
-                                    .size_6()
-                                    .bg(gpui::red()),
-                            )
-                    }),
-                ))
-                .child(Story::label("Player Backgrounds"))
-                .child(div().flex().gap_1().children(
-                    cx.theme().players().0.clone().iter_mut().map(|player| {
-                        div()
-                            .my_1()
-                            .rounded_xl()
-                            .flex()
-                            .items_center()
-                            .h_8()
-                            .py_0p5()
-                            .px_1p5()
-                            .bg(player.background)
-                            .child(
-                                div()
-                                    .relative()
-                                    .mx_neg_1()
-                                    .rounded_full()
-                                    .border_2()
-                                    .border_color(player.background)
-                                    .size(px(28.))
-                                    .child(
-                                        img("https://avatars.githubusercontent.com/u/1714999?v=4")
-                                            .rounded_full()
-                                            .size(px(24.))
-                                            .bg(gpui::red()),
-                                    ),
-                            )
-                            .child(
-                                div()
-                                    .relative()
-                                    .mx_neg_1()
-                                    .rounded_full()
-                                    .border_2()
-                                    .border_color(player.background)
-                                    .size(px(28.))
-                                    .child(
-                                        img("https://avatars.githubusercontent.com/u/1714999?v=4")
-                                            .rounded_full()
-                                            .size(px(24.))
-                                            .bg(gpui::red()),
-                                    ),
-                            )
-                            .child(
-                                div()
-                                    .relative()
-                                    .mx_neg_1()
-                                    .rounded_full()
-                                    .border_2()
-                                    .border_color(player.background)
-                                    .size(px(28.))
-                                    .child(
-                                        img("https://avatars.githubusercontent.com/u/1714999?v=4")
-                                            .rounded_full()
-                                            .size(px(24.))
-                                            .bg(gpui::red()),
-                                    ),
-                            )
-                    }),
-                ))
-                .child(Story::label("Player Selections"))
-                .child(div().flex().flex_col().gap_px().children(
-                    cx.theme().players().0.clone().iter_mut().map(|player| {
-                        div()
-                            .flex()
-                            .child(
-                                div()
-                                    .flex()
-                                    .flex_none()
-                                    .rounded_sm()
-                                    .px_0p5()
-                                    .text_color(cx.theme().colors().text)
-                                    .bg(player.selection)
-                                    .child("The brown fox jumped over the lazy dog."),
-                            )
-                            .child(div().flex_1())
-                    }),
-                )),
-        )
-    }
-}

crates/theme/src/theme.rs 🔗

@@ -9,13 +9,8 @@
 //! A theme is a collection of colors used to build a consistent appearance for UI components across the application.
 
 mod default_colors;
-mod default_theme;
+mod fallback_themes;
 mod font_family_cache;
-mod one_themes;
-/// A prelude for working with the theme system.
-///
-/// TODO: remove this. This only publishes default colors.
-pub mod prelude;
 mod registry;
 mod scale;
 mod schema;
@@ -26,7 +21,6 @@ use std::sync::Arc;
 
 use ::settings::{Settings, SettingsStore};
 pub use default_colors::*;
-pub use default_theme::*;
 pub use font_family_cache::*;
 pub use registry::*;
 pub use scale::*;

crates/theme/theme.md 🔗

@@ -1,15 +0,0 @@
-# Theme
-
-This crate provides the theme system for Zed.
-
-## Overview
-
-A theme is a collection of colors used to build a consistent appearance for UI components across the application.
-To produce a theme in Zed,
-
-A theme is made of two parts: A [ThemeFamily] and one or more [Theme]s.
-
-//
-A [ThemeFamily] contains metadata like theme name, author, and theme-specific [ColorScales] as well as a series of themes.
-
-- [ThemeColors] - A set of colors that are used to style the UI. Refer to the [ThemeColors] documentation for more information.

crates/theme/util/hex_to_hsla.py 🔗

@@ -1,35 +0,0 @@
-import colorsys
-import sys
-
-def hex_to_rgb(hex):
-    hex = hex.lstrip('#')
-    if len(hex) == 8: # 8 digit hex color
-        r, g, b, a = (int(hex[i:i+2], 16) for i in (0, 2, 4, 6))
-        return r, g, b, a / 255.0
-    else: # 6 digit hex color
-        return tuple(int(hex[i:i+2], 16) for i in (0, 2, 4)) + (1.0,)
-
-def rgb_to_hsla(rgb):
-    h, l, s = colorsys.rgb_to_hls(rgb[0]/255.0, rgb[1]/255.0, rgb[2]/255.0)
-    a = rgb[3] # alpha value
-    return (round(h * 360, 1), round(s * 100, 1), round(l * 100, 1), round(a, 3))
-
-def hex_to_hsla(hex):
-    return rgb_to_hsla(hex_to_rgb(hex))
-
-if len(sys.argv) != 2:
-    print("Usage: python util/hex_to_hsla.py <6 or 8 digit hex color or comma-separated list of colors>")
-else:
-    input_arg = sys.argv[1]
-    if ',' in input_arg: # comma-separated list of colors
-        hex_colors = input_arg.split(',')
-        hslas = [] # output array
-        for hex_color in hex_colors:
-            hex_color = hex_color.strip("'\" ")
-            h, s, l, a = hex_to_hsla(hex_color)
-            hslas.append(f"hsla({h} / 360., {s} / 100., {l} / 100., {a})")
-        print(hslas)
-    else: # single color
-        hex_color = input_arg.strip("'\"")
-        h, s, l, a = hex_to_hsla(hex_color)
-        print(f"hsla({h} / 360., {s} / 100., {l} / 100., {a})")