feat: component theme

This commit is contained in:
luoxiao 2024-05-03 00:32:12 +08:00
parent 9ab8367c21
commit b6b7df0a05
9 changed files with 181 additions and 204 deletions

View file

@ -1,9 +1,17 @@
[workspace]
resolver = "2"
members = ["thaw", "thaw_components", "thaw_utils", "demo", "demo_markdown"]
members = [
"thaw",
"thaw_components",
"thaw_macro",
"thaw_utils",
"demo",
"demo_markdown",
]
exclude = ["examples"]
[workspace.dependencies]
thaw = { version = "0.3.1", path = "./thaw" }
thaw_components = { version = "0.1.1", path = "./thaw_components" }
thaw_macro = { version = "0.1.0", path = "./thaw_macro" }
thaw_utils = { version = "0.0.3", path = "./thaw_utils" }

View file

@ -15,6 +15,7 @@ license = "MIT"
[dependencies]
leptos = { version = "0.6.10" }
thaw_components = { workspace = true }
thaw_macro = { workspace = true }
thaw_utils = { workspace = true }
web-sys = { version = "0.3.69", features = [
"DomRect",

View file

@ -58,92 +58,8 @@ pub fn ConfigProvider(
"--curveEasyEase: {};",
theme.common.curve_easy_ease
));
css_vars.push_str(&format!(
"--colorNeutralBackground1: {};",
theme.common.color_neutral_background_1
));
css_vars.push_str(&format!(
"--colorNeutralBackground1Hover: {};",
theme.common.color_neutral_background_1_hover
));
css_vars.push_str(&format!(
"--colorNeutralBackground1Pressed: {};",
theme.common.color_neutral_background_1_pressed
));
css_vars.push_str(&format!(
"--colorNeutralForeground1: {};",
theme.common.color_neutral_foreground_1
));
css_vars.push_str(&format!(
"--colorNeutralForeground1Hover: {};",
theme.common.color_neutral_foreground_1_hover
));
css_vars.push_str(&format!(
"--colorNeutralForeground1Pressed: {};",
theme.common.color_neutral_foreground_1_pressed
));
css_vars.push_str(&format!(
"--colorNeutralForeground2: {};",
theme.common.color_neutral_foreground_2
));
css_vars.push_str(&format!(
"--colorNeutralForeground2Hover: {};",
theme.common.color_neutral_foreground_2_hover
));
css_vars.push_str(&format!(
"--colorNeutralForeground2Pressed: {};",
theme.common.color_neutral_foreground_2_pressed
));
css_vars.push_str(&format!(
"--colorNeutralForeground2BrandHover: {};",
theme.common.color_neutral_foreground_2_brand_hover
));
css_vars.push_str(&format!(
"--colorNeutralForeground2BrandPressed: {};",
theme.common.color_neutral_foreground_2_brand_pressed
));
css_vars.push_str(&format!(
"--colorNeutralForegroundOnBrand: {};",
theme.common.color_neutral_foreground_on_brand
));
css_vars.push_str(&format!(
"--colorNeutralStroke1: {};",
theme.common.color_neutral_stroke_1
));
css_vars.push_str(&format!(
"--colorNeutralStroke1Hover: {};",
theme.common.color_neutral_stroke_1_hover
));
css_vars.push_str(&format!(
"--colorNeutralStroke1Pressed: {};",
theme.common.color_neutral_stroke_1_pressed
));
css_vars.push_str(&format!(
"--colorBrandBackground: {};",
theme.common.color_brand_background
));
css_vars.push_str(&format!(
"--colorBrandBackgroundHover: {};",
theme.common.color_brand_background_hover
));
css_vars.push_str(&format!(
"--colorBrandBackgroundPressed: {};",
theme.common.color_brand_background_pressed
));
css_vars.push_str(&format!(
"--colorSubtleBackground: {};",
theme.common.color_subtle_background
));
css_vars.push_str(&format!(
"--colorSubtleBackgroundHover {};",
theme.common.color_subtle_background_hover
));
css_vars.push_str(&format!(
"--colorSubtleBackgroundPressed: {};",
theme.common.color_subtle_background_pressed
));
theme.color.write_css_vars(&mut css_vars);
});
css_vars
});

View file

@ -11,9 +11,9 @@ pub fn GlobalStyle() -> impl IntoView {
.style()
.set_property("background-color", &theme.common.background_color);
_ = body.style().set_property("color", &theme.common.font_color);
_ = body
.style()
.set_property("font-size", &theme.common.font_size);
// _ = body
// .style()
// .set_property("font-size", &theme.common.font_size);
_ = body
.style()
.set_property("color-scheme", &theme.common.color_scheme);

View file

@ -0,0 +1,89 @@
use thaw_macro::WriteCSSVars;
#[derive(Clone, WriteCSSVars)]
pub struct ColorTheme {
pub color_neutral_background_1: String,
pub color_neutral_background_1_hover: String,
pub color_neutral_background_1_pressed: String,
pub color_neutral_foreground_1: String,
pub color_neutral_foreground_1_hover: String,
pub color_neutral_foreground_1_pressed: String,
pub color_neutral_foreground_2: String,
pub color_neutral_foreground_2_hover: String,
pub color_neutral_foreground_2_pressed: String,
pub color_neutral_foreground_2_brand_hover: String,
pub color_neutral_foreground_2_brand_pressed: String,
pub color_neutral_foreground_on_brand: String,
pub color_neutral_stroke_1: String,
pub color_neutral_stroke_1_hover: String,
pub color_neutral_stroke_1_pressed: String,
pub color_brand_background: String,
pub color_brand_background_hover: String,
pub color_brand_background_pressed: String,
pub color_subtle_background: String,
pub color_subtle_background_hover: String,
pub color_subtle_background_pressed: String,
pub color_transparent_background: String,
pub color_transparent_background_hover: String,
pub color_transparent_background_pressed: String,
}
impl ColorTheme {
pub fn light() -> Self {
Self {
color_neutral_background_1: "#fff".into(),
color_neutral_background_1_hover: "#f5f5f5".into(),
color_neutral_background_1_pressed: "#e0e0e0".into(),
color_neutral_foreground_1: "#242424".into(),
color_neutral_foreground_1_hover: "#242424".into(),
color_neutral_foreground_1_pressed: "#242424".into(),
color_neutral_foreground_2: "#424242".into(),
color_neutral_foreground_2_hover: "#242424".into(),
color_neutral_foreground_2_pressed: "#242424".into(),
color_neutral_foreground_2_brand_hover: "#0f6cbd".into(),
color_neutral_foreground_2_brand_pressed: "#115ea3".into(),
color_neutral_foreground_on_brand: "#fff".into(),
color_neutral_stroke_1: "#d1d1d1".into(),
color_neutral_stroke_1_hover: "#c7c7c7".into(),
color_neutral_stroke_1_pressed: "#b3b3b3".into(),
color_brand_background: "#0f6cbd".into(),
color_brand_background_hover: "#115ea3".into(),
color_brand_background_pressed: "#0c3b5e".into(),
color_subtle_background: "transparent".into(),
color_subtle_background_hover: "#f5f5f5".into(),
color_subtle_background_pressed: "#e0e0e0".into(),
color_transparent_background: "transparent".into(),
color_transparent_background_hover: "transparent".into(),
color_transparent_background_pressed: "transparent".into(),
}
}
pub fn dark() -> Self {
Self {
color_neutral_background_1: "#292929".into(),
color_neutral_background_1_hover: "#3d3d3d".into(),
color_neutral_background_1_pressed: "#1f1f1f".into(),
color_neutral_foreground_1: "#fff".into(),
color_neutral_foreground_1_hover: "#fff".into(),
color_neutral_foreground_1_pressed: "#fff".into(),
color_neutral_foreground_2: "#d6d6d6".into(),
color_neutral_foreground_2_hover: "#fff".into(),
color_neutral_foreground_2_pressed: "#fff".into(),
color_neutral_foreground_2_brand_hover: "#479ef5".into(),
color_neutral_foreground_2_brand_pressed: "#2886de".into(),
color_neutral_foreground_on_brand: "#fff".into(),
color_neutral_stroke_1: "#666666".into(),
color_neutral_stroke_1_hover: "#757575".into(),
color_neutral_stroke_1_pressed: "#6b6b6b".into(),
color_brand_background: "#115ea3".into(),
color_brand_background_hover: "#0f6cbd".into(),
color_brand_background_pressed: "#0c3b5e".into(),
color_subtle_background: "transparent".into(),
color_subtle_background_hover: "#383838".into(),
color_subtle_background_pressed: "#2e2e2e".into(),
color_transparent_background: "transparent".into(),
color_transparent_background_hover: "transparent".into(),
color_transparent_background_pressed: "transparent".into(),
}
}
}

View file

@ -21,31 +21,6 @@ pub struct CommonTheme {
pub color_error_hover: String,
pub color_error_active: String,
pub color_neutral_background_1: String,
pub color_neutral_background_1_hover: String,
pub color_neutral_background_1_pressed: String,
pub color_neutral_foreground_1: String,
pub color_neutral_foreground_1_hover: String,
pub color_neutral_foreground_1_pressed: String,
pub color_neutral_foreground_2: String,
pub color_neutral_foreground_2_hover: String,
pub color_neutral_foreground_2_pressed: String,
pub color_neutral_foreground_2_brand_hover: String,
pub color_neutral_foreground_2_brand_pressed: String,
pub color_neutral_foreground_on_brand: String,
pub color_neutral_stroke_1: String,
pub color_neutral_stroke_1_hover: String,
pub color_neutral_stroke_1_pressed: String,
pub color_brand_background: String,
pub color_brand_background_hover: String,
pub color_brand_background_pressed: String,
pub color_subtle_background: String,
pub color_subtle_background_hover: String,
pub color_subtle_background_pressed: String,
pub color_transparent_background: String,
pub color_transparent_background_hover: String,
pub color_transparent_background_pressed: String,
pub font_size_base_300: String,
pub line_height_base300: String,
@ -63,24 +38,11 @@ pub struct CommonTheme {
pub duration_faster: String,
pub curve_easy_ease: String,
pub font_size: String,
pub font_size_tiny: String,
pub font_size_small: String,
pub font_size_medium: String,
pub font_size_large: String,
pub font_size_huge: String,
pub height_tiny: String,
pub height_small: String,
pub height_medium: String,
pub height_large: String,
pub line_height: String,
pub line_height_small: String,
pub line_height_medium: String,
pub line_height_large: String,
pub line_height_huge: String,
pub border_radius: String,
pub border_radius_small: String,
pub border_radius_large: String,
@ -107,31 +69,6 @@ impl CommonTheme {
color_error_hover: "".into(),
color_error_active: "".into(),
color_neutral_background_1: "".into(),
color_neutral_background_1_hover: "".into(),
color_neutral_background_1_pressed: "".into(),
color_neutral_foreground_1: "".into(),
color_neutral_foreground_1_hover: "".into(),
color_neutral_foreground_1_pressed: "".into(),
color_neutral_foreground_2: "".into(),
color_neutral_foreground_2_hover: "".into(),
color_neutral_foreground_2_pressed: "".into(),
color_neutral_foreground_2_brand_hover: "".into(),
color_neutral_foreground_2_brand_pressed: "".into(),
color_neutral_foreground_on_brand: "#fff".into(),
color_neutral_stroke_1: "".into(),
color_neutral_stroke_1_hover: "".into(),
color_neutral_stroke_1_pressed: "".into(),
color_brand_background: "".into(),
color_brand_background_hover: "".into(),
color_brand_background_pressed: "".into(),
color_subtle_background: "transparent".into(),
color_subtle_background_hover: "".into(),
color_subtle_background_pressed: "".into(),
color_transparent_background: "transparent".into(),
color_transparent_background_hover: "transparent".into(),
color_transparent_background_pressed: "transparent".into(),
font_size_base_300: "14px".into(),
line_height_base300: "20px".into(),
@ -149,24 +86,11 @@ impl CommonTheme {
duration_faster: "100ms".into(),
curve_easy_ease: "cubic-bezier(0.33,0,0.67,1)".into(),
font_size: "14px".into(),
font_size_tiny: "12px".into(),
font_size_small: "14px".into(),
font_size_medium: "14px".into(),
font_size_large: "15px".into(),
font_size_huge: "16px".into(),
height_tiny: "22px".into(),
height_small: "28px".into(),
height_medium: "34px".into(),
height_large: "40px".into(),
line_height: "22px".into(),
line_height_small: "22px".into(),
line_height_medium: "22px".into(),
line_height_large: "23px".into(),
line_height_huge: "24px".into(),
border_radius: "3px".into(),
border_radius_small: "2px".into(),
border_radius_large: "8px".into(),
@ -193,25 +117,7 @@ impl ThemeMethod for CommonTheme {
color_error_hover: "#de576d".into(),
color_error_active: "#ab1f3f".into(),
border_color: "#e5e8eb".into(),
color_neutral_background_1: "#fff".into(),
color_neutral_background_1_hover: "#f5f5f5".into(),
color_neutral_background_1_pressed: "#e0e0e0".into(),
color_neutral_foreground_1: "#242424".into(),
color_neutral_foreground_1_hover: "#242424".into(),
color_neutral_foreground_1_pressed: "#242424".into(),
color_neutral_foreground_2: "#424242".into(),
color_neutral_foreground_2_hover: "#242424".into(),
color_neutral_foreground_2_pressed: "#242424".into(),
color_neutral_foreground_2_brand_hover: "#0f6cbd".into(),
color_neutral_foreground_2_brand_pressed: "#115ea3".into(),
color_neutral_stroke_1: "#d1d1d1".into(),
color_neutral_stroke_1_hover: "#c7c7c7".into(),
color_neutral_stroke_1_pressed: "#b3b3b3".into(),
color_brand_background: "#0f6cbd".into(),
color_brand_background_hover: "#115ea3".into(),
color_brand_background_pressed: "#0c3b5e".into(),
color_subtle_background_hover: "#f5f5f5".into(),
color_subtle_background_pressed: "#e0e0e0".into(),
..CommonTheme::common()
}
}
@ -235,25 +141,6 @@ impl ThemeMethod for CommonTheme {
color_error_hover: "#de576d".into(),
color_error_active: "#e57272".into(),
border_color: "#1f2537".into(),
color_neutral_background_1: "#292929".into(),
color_neutral_background_1_hover: "#3d3d3d".into(),
color_neutral_background_1_pressed: "#1f1f1f".into(),
color_neutral_foreground_1: "#fff".into(),
color_neutral_foreground_1_hover: "#fff".into(),
color_neutral_foreground_1_pressed: "#fff".into(),
color_neutral_foreground_2: "#d6d6d6".into(),
color_neutral_foreground_2_hover: "#fff".into(),
color_neutral_foreground_2_pressed: "#fff".into(),
color_neutral_foreground_2_brand_hover: "#479ef5".into(),
color_neutral_foreground_2_brand_pressed: "#2886de".into(),
color_neutral_stroke_1: "#666666".into(),
color_neutral_stroke_1_hover: "#757575".into(),
color_neutral_stroke_1_pressed: "#6b6b6b".into(),
color_brand_background: "#115ea3".into(),
color_brand_background_hover: "#0f6cbd".into(),
color_brand_background_pressed: "#0c3b5e".into(),
color_subtle_background_hover: "#383838".into(),
color_subtle_background_pressed: "#2e2e2e".into(),
..CommonTheme::common()
}
}

View file

@ -1,6 +1,8 @@
mod common;
mod color;
use self::common::CommonTheme;
pub use color::ColorTheme;
use crate::{
mobile::{NavBarTheme, TabbarTheme},
AlertTheme, AnchorTheme, AutoCompleteTheme, AvatarTheme, BackTopTheme, BreadcrumbTheme,
@ -20,6 +22,7 @@ pub trait ThemeMethod {
pub struct Theme {
pub name: String,
pub common: CommonTheme,
pub color: ColorTheme,
pub button: ButtonTheme,
pub input: InputTheme,
pub menu: MenuTheme,
@ -56,6 +59,7 @@ impl Theme {
Self {
name: "light".into(),
common: CommonTheme::light(),
color: ColorTheme::light(),
button: ButtonTheme::light(),
input: InputTheme::light(),
menu: MenuTheme::light(),
@ -91,6 +95,7 @@ impl Theme {
Self {
name: "dark".into(),
common: CommonTheme::dark(),
color: ColorTheme::dark(),
button: ButtonTheme::dark(),
input: InputTheme::dark(),
menu: MenuTheme::dark(),

14
thaw_macro/Cargo.toml Normal file
View file

@ -0,0 +1,14 @@
[package]
name = "thaw_macro"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true
[dependencies]
quote = "1.0.36"
syn = "2.0.60"
proc-macro2 = "1.0.81"

57
thaw_macro/src/lib.rs Normal file
View file

@ -0,0 +1,57 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};
#[proc_macro_derive(WriteCSSVars)]
pub fn write_css_vars(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let struct_name = &input.ident;
let data = match input.data {
Data::Struct(data) => data,
_ => panic!("Expected a struct!"),
};
let mut css_var_names = vec![];
let mut field_names = vec![];
match data.fields {
Fields::Named(fields) => {
for field in fields.named {
let field_name = field.ident.unwrap();
css_var_names.push(format!(
"--{}: {{}};",
to_camel_case(field_name.to_string())
));
field_names.push(field_name);
}
}
_ => panic!("Expected named fields!"),
};
let field_names = field_names.iter();
quote! {
impl #struct_name {
pub fn write_css_vars(&self, css_vars: &mut String) {
#(css_vars.push_str(&format!(#css_var_names, self.#field_names));)*
}
}
}
.into()
}
fn to_camel_case(s: String) -> String {
let mut camel_case = String::new();
let mut capitalize_next = false;
for c in s.chars() {
if c.is_alphanumeric() {
if capitalize_next {
camel_case.push(c.to_ascii_uppercase());
capitalize_next = false;
} else {
camel_case.push(c.to_ascii_lowercase());
}
} else {
capitalize_next = true;
}
}
camel_case
}