From 773ad6bfd154b9f14b9b2b7009fd5d53926f9e3f Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 3 Oct 2024 10:27:19 -0400 Subject: [PATCH] Document the `theme` crate (#18690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR enables required documentation for the `theme` crate starts on documenting it. The end goal is to have all meaningful documentation in the crate filled out – However I'm not sure that just adding `#![deny(missing_docs)]` to the whole crate is the right approach. I don't know that having 200+ "The color of the _ color" field docs is useful however–In the short term I've excluded some of the modules that contain structs with a ton of fields (`colors, `status`, etc.) until we decide what the right solution here is. Next steps are to clean up the crate, removing unused modules or those with low usage in favor of other approaches. Changes in this PR: - Enable the `deny(missing_docs)` lint for the `theme` crate - Start documenting a subset of the crate. - Enable `#![allow(missing_docs)]` for some modules. Release Notes: - N/A --- crates/theme/src/default_colors.rs | 15 +++-- crates/theme/src/default_theme.rs | 3 + crates/theme/src/font_family_cache.rs | 3 + crates/theme/src/registry.rs | 11 ++++ crates/theme/src/scale.rs | 1 + crates/theme/src/schema.rs | 2 + crates/theme/src/settings.rs | 70 +++++++++++++++++++++- crates/theme/src/styles/accents.rs | 3 + crates/theme/src/styles/colors.rs | 2 + crates/theme/src/styles/players.rs | 2 + crates/theme/src/styles/status.rs | 2 + crates/theme/src/styles/stories/color.rs | 1 + crates/theme/src/styles/stories/players.rs | 1 + crates/theme/src/styles/syntax.rs | 2 + crates/theme/src/styles/system.rs | 2 + crates/theme/src/theme.rs | 41 ++++++++++++- 16 files changed, 152 insertions(+), 9 deletions(-) diff --git a/crates/theme/src/default_colors.rs b/crates/theme/src/default_colors.rs index a7521bd374d1c364975dd20e3752f55ab9750c73..49c216c0e07e78b02b33d409f4518ae3ad28f34d 100644 --- a/crates/theme/src/default_colors.rs +++ b/crates/theme/src/default_colors.rs @@ -8,12 +8,13 @@ pub(crate) fn neutral() -> ColorScaleSet { sand() } -// Note: We aren't currently making use of the default colors, as all of the -// themes have a value set for each color. -// -// We'll need to revisit these once we're ready to launch user themes, which may -// not specify a value for each color (and thus should fall back to the defaults). +/// The default colors for the theme. +/// +/// Themes that do not specify all colors are refined off of these defaults. impl ThemeColors { + /// Returns the default colors for light themes. + /// + /// Themes that do not specify all colors are refined off of these defaults. pub fn light() -> Self { let system = SystemColors::default(); @@ -114,6 +115,9 @@ impl ThemeColors { } } + /// Returns the default colors for dark themes. + /// + /// Themes that do not specify all colors are refined off of these defaults. pub fn dark() -> Self { let system = SystemColors::default(); @@ -247,6 +251,7 @@ impl TryFrom for ColorScaleSet { } } +/// Color scales used to build the default themes. pub fn default_color_scales() -> ColorScales { ColorScales { gray: gray(), diff --git a/crates/theme/src/default_theme.rs b/crates/theme/src/default_theme.rs index 6722b847badb96b9af5498ca72e4bcb853dc3440..580634091653306c390971b29c1e4860237f915b 100644 --- a/crates/theme/src/default_theme.rs +++ b/crates/theme/src/default_theme.rs @@ -45,6 +45,9 @@ pub(crate) fn zed_pro_moonlight() -> Theme { } } +/// 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(), diff --git a/crates/theme/src/font_family_cache.rs b/crates/theme/src/font_family_cache.rs index c9583b9e8d3bc7ad3136b249e6bc784d71d4951f..755d829902a48fd8fed3702f1d129749238e673f 100644 --- a/crates/theme/src/font_family_cache.rs +++ b/crates/theme/src/font_family_cache.rs @@ -25,14 +25,17 @@ struct GlobalFontFamilyCache(Arc); impl Global for GlobalFontFamilyCache {} impl FontFamilyCache { + /// Initializes the global font family cache. pub fn init_global(cx: &mut AppContext) { cx.default_global::(); } + /// Returns the global font family cache. pub fn global(cx: &AppContext) -> Arc { GlobalFontFamilyCache::global(cx).0.clone() } + /// Returns the list of font families. pub fn list_font_families(&self, cx: &AppContext) -> Vec { if self.state.read().loaded_at.is_some() { return self.state.read().font_families.clone(); diff --git a/crates/theme/src/registry.rs b/crates/theme/src/registry.rs index b70377f4408b9845ae633dd5a6f56f530d355160..a77ab141a6547b41a74fca102134efbf834aa7f6 100644 --- a/crates/theme/src/registry.rs +++ b/crates/theme/src/registry.rs @@ -17,9 +17,12 @@ use crate::{ ThemeStyles, }; +/// The metadata for a theme. #[derive(Debug, Clone)] pub struct ThemeMeta { + /// The name of the theme. pub name: SharedString, + /// The appearance of the theme. pub appearance: Appearance, } @@ -38,6 +41,7 @@ struct ThemeRegistryState { themes: HashMap>, } +/// The registry for themes. pub struct ThemeRegistry { state: RwLock, assets: Box, @@ -61,6 +65,7 @@ impl ThemeRegistry { cx.set_global(GlobalThemeRegistry(Arc::new(ThemeRegistry::new(assets)))); } + /// Creates a new [`ThemeRegistry`] with the given [`AssetSource`]. pub fn new(assets: Box) -> Self { let registry = Self { state: RwLock::new(ThemeRegistryState { @@ -99,6 +104,7 @@ impl ThemeRegistry { } } + /// Inserts user themes into the registry. pub fn insert_user_themes(&self, themes: impl IntoIterator) { self.insert_themes(themes.into_iter().map(|user_theme| { let mut theme_colors = match user_theme.appearance { @@ -185,16 +191,19 @@ impl ThemeRegistry { .retain(|name, _| !themes_to_remove.contains(name)) } + /// Removes all themes from the registry. pub fn clear(&mut self) { self.state.write().themes.clear(); } + /// Returns the names of all themes in the registry. pub fn list_names(&self, _staff: bool) -> Vec { let mut names = self.state.read().themes.keys().cloned().collect::>(); names.sort(); names } + /// Returns the metadata of all themes in the registry. pub fn list(&self, _staff: bool) -> Vec { self.state .read() @@ -207,6 +216,7 @@ impl ThemeRegistry { .collect() } + /// Returns the theme with the given name. pub fn get(&self, name: &str) -> Result> { self.state .read() @@ -261,6 +271,7 @@ impl ThemeRegistry { Ok(()) } + /// Asynchronously reads the user theme from the specified path. pub async fn read_user_theme(theme_path: &Path, fs: Arc) -> Result { let reader = fs.open_sync(theme_path).await?; let theme_family: ThemeFamilyContent = serde_json_lenient::from_reader(reader)?; diff --git a/crates/theme/src/scale.rs b/crates/theme/src/scale.rs index 1146090edcc1e7fbef1f8cc09e43377db4183862..a70dcb9789a3c86441ea9abc81afdb23a070492d 100644 --- a/crates/theme/src/scale.rs +++ b/crates/theme/src/scale.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{AppContext, Hsla, SharedString}; use crate::{ActiveTheme, Appearance}; diff --git a/crates/theme/src/schema.rs b/crates/theme/src/schema.rs index 91863061236f2475b5ed28d8ec9fa91ec0d37340..af334d8aed54b9a9b9169a038445c5924ce6d65e 100644 --- a/crates/theme/src/schema.rs +++ b/crates/theme/src/schema.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use anyhow::Result; use gpui::{FontStyle, FontWeight, HighlightStyle, Hsla, WindowBackgroundAppearance}; use indexmap::IndexMap; diff --git a/crates/theme/src/settings.rs b/crates/theme/src/settings.rs index 86383cec8ea07933a98198fb766b264b601a9d25..0c8ea782cd6081f756affd5d64b50beba3e91115 100644 --- a/crates/theme/src/settings.rs +++ b/crates/theme/src/settings.rs @@ -35,6 +35,9 @@ const MIN_LINE_HEIGHT: f32 = 1.0; Deserialize, JsonSchema, )] + +/// Specifies the density of the UI. +/// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078) #[serde(rename_all = "snake_case")] pub enum UiDensity { /// A denser UI with tighter spacing and smaller elements. @@ -50,6 +53,8 @@ pub enum UiDensity { } impl UiDensity { + /// The spacing ratio of a given density. + /// TODO: Standardize usage throughout the app or remove pub fn spacing_ratio(self) -> f32 { match self { UiDensity::Compact => 0.75, @@ -80,17 +85,43 @@ impl From for String { } } +/// Customizable settings for the UI and theme system. #[derive(Clone)] pub struct ThemeSettings { + /// The UI font size. Determines the size of text in the UI, + /// as well as the size of a [gpui::Rems] unit. + /// + /// Changing this will impact the size of all UI elements. pub ui_font_size: Pixels, + /// The font used for UI elements. pub ui_font: Font, - pub buffer_font: Font, + /// The font size used for buffers, and the terminal. + /// + /// The terminal font size can be overridden using it's own setting. pub buffer_font_size: Pixels, + /// The font used for buffers, and the terminal. + /// + /// The terminal font family can be overridden using it's own setting. + pub buffer_font: Font, + /// The line height for buffers, and the terminal. + /// + /// Changing this may affect the spacing of some UI elements. + /// + /// The terminal font family can be overridden using it's own setting. pub buffer_line_height: BufferLineHeight, + /// The current theme selection. + /// TODO: Document this further pub theme_selection: Option, + /// The active theme. pub active_theme: Arc, + /// Manual overrides for the active theme. + /// + /// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078) pub theme_overrides: Option, + /// The density of the UI. + /// Note: This setting is still experimental. See [this tracking issue]( pub ui_density: UiDensity, + /// The amount of fading applied to unnecessary code. pub unnecessary_code_fade: f32, } @@ -181,15 +212,21 @@ pub(crate) struct AdjustedUiFontSize(Pixels); impl Global for AdjustedUiFontSize {} +/// Represents the selection of a theme, which can be either static or dynamic. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] #[serde(untagged)] pub enum ThemeSelection { + /// A static theme selection, represented by a single theme name. Static(#[schemars(schema_with = "theme_name_ref")] String), + /// A dynamic theme selection, which can change based the [ThemeMode]. Dynamic { + /// The mode used to determine which theme to use. #[serde(default)] mode: ThemeMode, + /// The theme to use for light mode. #[schemars(schema_with = "theme_name_ref")] light: String, + /// The theme to use for dark mode. #[schemars(schema_with = "theme_name_ref")] dark: String, }, @@ -199,6 +236,12 @@ fn theme_name_ref(_: &mut SchemaGenerator) -> Schema { Schema::new_ref("#/definitions/ThemeName".into()) } +// TODO: Rename ThemeMode -> ThemeAppearanceMode +/// The mode use to select a theme. +/// +/// `Light` and `Dark` will select their respective themes. +/// +/// `System` will select the theme based on the system's appearance. #[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum ThemeMode { @@ -214,6 +257,7 @@ pub enum ThemeMode { } impl ThemeSelection { + /// Returns the theme name for the selected [ThemeMode]. pub fn theme(&self, system_appearance: Appearance) -> &str { match self { Self::Static(theme) => theme, @@ -228,6 +272,7 @@ impl ThemeSelection { } } + /// Returns the [ThemeMode] for the [ThemeSelection]. pub fn mode(&self) -> Option { match self { ThemeSelection::Static(_) => None, @@ -327,6 +372,7 @@ impl ThemeSettingsContent { } } + /// Sets the mode for the theme. pub fn set_mode(&mut self, mode: ThemeMode) { if let Some(selection) = self.theme.as_mut() { match selection { @@ -355,16 +401,23 @@ impl ThemeSettingsContent { } } +/// The buffer's line height. #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)] #[serde(rename_all = "snake_case")] pub enum BufferLineHeight { + /// A less dense line height. #[default] Comfortable, + /// The default line height. Standard, + /// A custom line height. + /// + /// A line height of 1.0 is the height of the buffer's font size. Custom(f32), } impl BufferLineHeight { + /// Returns the value of the line height. pub fn value(&self) -> f32 { match self { BufferLineHeight::Comfortable => 1.618, @@ -375,12 +428,15 @@ impl BufferLineHeight { } impl ThemeSettings { + /// Returns the [AdjustedBufferFontSize]. pub fn buffer_font_size(&self, cx: &AppContext) -> Pixels { cx.try_global::() .map_or(self.buffer_font_size, |size| size.0) .max(MIN_FONT_SIZE) } + // TODO: Rename: `line_height` -> `buffer_line_height` + /// Returns the buffer's line height. pub fn line_height(&self) -> f32 { f32::max(self.buffer_line_height.value(), MIN_LINE_HEIGHT) } @@ -433,6 +489,7 @@ impl ThemeSettings { } } +/// Observe changes to the adjusted buffer font size. pub fn observe_buffer_font_size_adjustment( cx: &mut ViewContext, f: impl 'static + Fn(&mut V, &mut ViewContext), @@ -440,6 +497,7 @@ pub fn observe_buffer_font_size_adjustment( cx.observe_global::(f) } +/// Sets the adjusted buffer font size. pub fn adjusted_font_size(size: Pixels, cx: &mut AppContext) -> Pixels { if let Some(AdjustedBufferFontSize(adjusted_size)) = cx.try_global::() { let buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size; @@ -451,12 +509,14 @@ pub fn adjusted_font_size(size: Pixels, cx: &mut AppContext) -> Pixels { .max(MIN_FONT_SIZE) } +/// Returns the adjusted buffer font size. pub fn get_buffer_font_size(cx: &AppContext) -> Pixels { let buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size; cx.try_global::() .map_or(buffer_font_size, |adjusted_size| adjusted_size.0) } +/// Adjusts the buffer font size. pub fn adjust_buffer_font_size(cx: &mut AppContext, f: fn(&mut Pixels)) { let buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size; let mut adjusted_size = cx @@ -469,10 +529,12 @@ pub fn adjust_buffer_font_size(cx: &mut AppContext, f: fn(&mut Pixels)) { cx.refresh(); } +/// Returns whether the buffer font size has been adjusted. pub fn has_adjusted_buffer_font_size(cx: &mut AppContext) -> bool { cx.has_global::() } +/// Resets the buffer font size to the default value. pub fn reset_buffer_font_size(cx: &mut AppContext) { if cx.has_global::() { cx.remove_global::(); @@ -480,6 +542,8 @@ pub fn reset_buffer_font_size(cx: &mut AppContext) { } } +// TODO: Make private, change usages to use `get_ui_font_size` instead. +#[allow(missing_docs)] pub fn setup_ui_font(cx: &mut WindowContext) -> gpui::Font { let (ui_font, ui_font_size) = { let theme_settings = ThemeSettings::get_global(cx); @@ -491,12 +555,14 @@ pub fn setup_ui_font(cx: &mut WindowContext) -> gpui::Font { ui_font } +/// Gets the adjusted UI font size. pub fn get_ui_font_size(cx: &AppContext) -> Pixels { let ui_font_size = ThemeSettings::get_global(cx).ui_font_size; cx.try_global::() .map_or(ui_font_size, |adjusted_size| adjusted_size.0) } +/// Sets the adjusted UI font size. pub fn adjust_ui_font_size(cx: &mut AppContext, f: fn(&mut Pixels)) { let ui_font_size = ThemeSettings::get_global(cx).ui_font_size; let mut adjusted_size = cx @@ -509,10 +575,12 @@ pub fn adjust_ui_font_size(cx: &mut AppContext, f: fn(&mut Pixels)) { cx.refresh(); } +/// Returns whether the UI font size has been adjusted. pub fn has_adjusted_ui_font_size(cx: &mut AppContext) -> bool { cx.has_global::() } +/// Resets the UI font size to the default value. pub fn reset_ui_font_size(cx: &mut AppContext) { if cx.has_global::() { cx.remove_global::(); diff --git a/crates/theme/src/styles/accents.rs b/crates/theme/src/styles/accents.rs index dfcd19911b26f60280ed2e2e82ed158337f876f6..e4d7f03cf622016d353914ffc4598c781ee13d5a 100644 --- a/crates/theme/src/styles/accents.rs +++ b/crates/theme/src/styles/accents.rs @@ -20,6 +20,7 @@ impl Default for AccentColors { } impl AccentColors { + /// Returns the set of dark accent colors. pub fn dark() -> Self { Self(vec![ blue().dark().step_9(), @@ -38,6 +39,7 @@ impl AccentColors { ]) } + /// Returns the set of light accent colors. pub fn light() -> Self { Self(vec![ blue().light().step_9(), @@ -58,6 +60,7 @@ impl AccentColors { } impl AccentColors { + /// Returns the color for the given index. pub fn color_for_index(&self, index: u32) -> Hsla { self.0[index as usize % self.0.len()] } diff --git a/crates/theme/src/styles/colors.rs b/crates/theme/src/styles/colors.rs index 225275f37b6191ab45fa1408c1a1a7a00deb4fda..881a68334dcf647325a25dc844d504da31d6082c 100644 --- a/crates/theme/src/styles/colors.rs +++ b/crates/theme/src/styles/colors.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::{Hsla, WindowBackgroundAppearance}; use refineable::Refineable; use std::sync::Arc; diff --git a/crates/theme/src/styles/players.rs b/crates/theme/src/styles/players.rs index e80c7161b15b129a64dbd8d53070979f3fe1031a..130721033239ce67bf2fa0d527cb37e529566c1c 100644 --- a/crates/theme/src/styles/players.rs +++ b/crates/theme/src/styles/players.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::Hsla; use serde_derive::Deserialize; diff --git a/crates/theme/src/styles/status.rs b/crates/theme/src/styles/status.rs index 854b876ac20b33702f9f4cce467c162e610ad125..84afae701d0f099beea955b65a7828c6c0df623a 100644 --- a/crates/theme/src/styles/status.rs +++ b/crates/theme/src/styles/status.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::Hsla; use refineable::Refineable; diff --git a/crates/theme/src/styles/stories/color.rs b/crates/theme/src/styles/stories/color.rs index 90e84bcf0f2ded0a2404526ff390281026f97b36..8e6c86ba762ba8ef760e49a0a7148ce0412a4446 100644 --- a/crates/theme/src/styles/stories/color.rs +++ b/crates/theme/src/styles/stories/color.rs @@ -4,6 +4,7 @@ use story::Story; use crate::{default_color_scales, ColorScaleStep}; +/// The story showcasing all the default color scales pub struct ColorsStory; impl Render for ColorsStory { diff --git a/crates/theme/src/styles/stories/players.rs b/crates/theme/src/styles/stories/players.rs index 2b356670bf66a62676c05d166ec41120ca9062cf..0d50c6edc9afcd3eb825f28157f438edae40fc09 100644 --- a/crates/theme/src/styles/stories/players.rs +++ b/crates/theme/src/styles/stories/players.rs @@ -3,6 +3,7 @@ use story::Story; use crate::{ActiveTheme, PlayerColors}; +/// The story showcasing the player colors pub struct PlayerStory; impl Render for PlayerStory { diff --git a/crates/theme/src/styles/syntax.rs b/crates/theme/src/styles/syntax.rs index 8016445c16c6af0f30a0d529e669564ab6e0f505..0a97ff77f23c8eb569e422684b6ba85272665cd8 100644 --- a/crates/theme/src/styles/syntax.rs +++ b/crates/theme/src/styles/syntax.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use std::sync::Arc; use gpui::{HighlightStyle, Hsla}; diff --git a/crates/theme/src/styles/system.rs b/crates/theme/src/styles/system.rs index aeb0865155d68aa8e167421b1ce79895120203ff..54e892b79c49f96e66c3817e9750fed3504327da 100644 --- a/crates/theme/src/styles/system.rs +++ b/crates/theme/src/styles/system.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::{hsla, Hsla}; #[derive(Clone)] diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index af38c9efc6f7ec21cca313a5923f5b21394a6fc5..a6ca59d734e245525684f83c1e15ff73819639a4 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -1,3 +1,5 @@ +#![deny(missing_docs)] + //! # Theme //! //! This crate provides the theme system for Zed. @@ -10,6 +12,9 @@ mod default_colors; mod default_theme; 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; @@ -35,16 +40,22 @@ use gpui::{ }; use serde::Deserialize; +/// Defines window border radius for platforms that use client side decorations. +pub const CLIENT_SIDE_DECORATION_ROUNDING: Pixels = px(10.0); +/// Defines window shadow size for platforms that use client side decorations. +pub const CLIENT_SIDE_DECORATION_SHADOW: Pixels = px(10.0); + +/// The appearance of the theme. #[derive(Debug, PartialEq, Clone, Copy, Deserialize)] pub enum Appearance { + /// A light appearance. Light, + /// A dark appearance. Dark, } -pub const CLIENT_SIDE_DECORATION_ROUNDING: Pixels = px(10.0); -pub const CLIENT_SIDE_DECORATION_SHADOW: Pixels = px(10.0); - impl Appearance { + /// Returns whether the appearance is light. pub fn is_light(&self) -> bool { match self { Self::Light => true, @@ -62,6 +73,7 @@ impl From for Appearance { } } +/// Which themes should be loaded. This is used primarlily for testing. pub enum LoadThemes { /// Only load the base theme. /// @@ -72,6 +84,7 @@ pub enum LoadThemes { All(Box), } +/// Initialize the theme system. pub fn init(themes_to_load: LoadThemes, cx: &mut AppContext) { let (assets, load_user_themes) = match themes_to_load { LoadThemes::JustBase => (Box::new(()) as Box, false), @@ -97,7 +110,9 @@ pub fn init(themes_to_load: LoadThemes, cx: &mut AppContext) { .detach(); } +/// Implementing this trait allows accessing the active theme. pub trait ActiveTheme { + /// Returns the active theme. fn theme(&self) -> &Arc; } @@ -107,21 +122,39 @@ impl ActiveTheme for AppContext { } } +/// A theme family is a grouping of themes under a single name. +/// +/// For example, the "One" theme family contains the "One Light" and "One Dark" themes. +/// +/// It can also be used to package themes with many variants. +/// +/// For example, the "Atelier" theme family contains "Cave", "Dune", "Estuary", "Forest", "Heath", etc. pub struct ThemeFamily { + /// The unique identifier for the theme family. pub id: String, + /// The name of the theme family. This will be displayed in the UI, such as when adding or removing a theme family. pub name: SharedString, + /// The author of the theme family. pub author: SharedString, + /// The [Theme]s in the family. pub themes: Vec, + /// The color scales used by the themes in the family. + /// Note: This will be removed in the future. pub scales: ColorScales, } impl ThemeFamily {} +/// A theme is the primary mechanism for defining the appearance of the UI. #[derive(Clone)] pub struct Theme { + /// The unique identifier for the theme. pub id: String, + /// The name of the theme. pub name: SharedString, + /// The appearance of the theme (light or dark). pub appearance: Appearance, + /// The colors and other styles for the theme. pub styles: ThemeStyles, } @@ -181,6 +214,8 @@ impl Theme { } } +/// Compounds a color with an alpha value. +/// TODO: Replace this with a method on Hsla. pub fn color_alpha(color: Hsla, alpha: f32) -> Hsla { let mut color = color; color.a = alpha;