From c50c05bc16650e04172d6e3ea7714a087f812f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=8A=E6=AC=A7?= Date: Tue, 29 Oct 2024 23:40:39 +0800 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20theme=20context=20in?= =?UTF-8?q?stead=20of=20hard-code=20HTML=20template.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/components/src/form/button/button.rs | 52 ++++---- .../src/form/button/button_group.rs | 12 +- packages/macro-types/src/register.rs | 2 +- packages/theme/src/components/form/button.rs | 14 +-- packages/theme/src/context.rs | 111 ++++++++++++++++++ packages/theme/src/global_states.rs | 86 -------------- packages/theme/src/lib.rs | 2 +- packages/theme/src/types/color.rs | 46 ++++++-- website/Cargo.toml | 1 + website/examples/dev/render.rs | 15 --- website/src/app.rs | 48 +------- website/src/pages/component.rs | 12 ++ 12 files changed, 203 insertions(+), 198 deletions(-) create mode 100644 packages/theme/src/context.rs delete mode 100644 packages/theme/src/global_states.rs diff --git a/packages/components/src/form/button/button.rs b/packages/components/src/form/button/button.rs index 4709d85..bb109ea 100644 --- a/packages/components/src/form/button/button.rs +++ b/packages/components/src/form/button/button.rs @@ -24,7 +24,7 @@ pub struct Props { #[styled_component] pub fn Button(props: &Props) -> Html { - let radius_type = use_context::(); + let radius_type = use_context::(); let radius_type = match &radius_type { Some(ctx) => ctx.border_radius_type, None => BorderRadiusType::Default, @@ -127,33 +127,33 @@ pub fn Button(props: &Props) -> Html { height: 100%; border: 1px solid transparent; - box-shadow: 1px 1px 4px 0 var(--color-shadow-rgba); + box-shadow: 1px 1px 4px 0 var(--color-shadow); transition: all 0.3s; &[data-color="primary"] { - background-color: rgba(var(--color-primary), 0.8); - border-color: rgba(var(--color-primary), 0.8); + background-color: var(--color-primary-most); + border-color: var(--color-primary-most); } &[data-color="secondary"] { - background-color: rgba(var(--color-secondary), 0.8); - border-color: rgba(var(--color-secondary), 0.8); + background-color: var(--color-secondary-most); + border-color: var(--color-secondary-most); } &[data-color="success"] { - background-color: rgba(var(--color-success), 0.8); - border-color: rgba(var(--color-success), 0.8); + background-color: var(--color-success-most); + border-color: var(--color-success-most); } &[data-color="error"] { - background-color: rgba(var(--color-error), 0.8); - border-color: rgba(var(--color-error), 0.8); + background-color: var(--color-error-most); + border-color: var(--color-error-most); } &[data-color="info"] { - background-color: rgba(var(--color-info), 0.8); - border-color: rgba(var(--color-info), 0.8); + background-color: var(--color-info-most); + border-color: var(--color-info-most); } &[data-color="warning"] { - background-color: rgba(var(--color-warning), 0.8); - border-color: rgba(var(--color-warning), 0.8); + background-color: var(--color-warning-most); + border-color: var(--color-warning-most); } &[data-border-radius-type="default"] { @@ -172,8 +172,8 @@ pub fn Button(props: &Props) -> Html { &[data-style="outlined"] { backdrop-filter: blur(4px); } - &[data-style="outlined"]&[data-state="none"], - &[data-style="outlined"]&[data-state="hover"] { + &[data-style="outlined"] &[data-state="none"], + &[data-style="outlined"] &[data-state="hover"] { background-color: transparent; } &[data-style="basic"] { @@ -220,7 +220,7 @@ pub fn Button(props: &Props) -> Html { width: 100%; height: 100%; border-radius: 4px; - box-shadow: 1px 1px 4px 0 var(--color-shadow-rgba); + box-shadow: 1px 1px 4px 0 var(--color-shadow); opacity: 0; z-index: -1; @@ -276,22 +276,22 @@ pub fn Button(props: &Props) -> Html { transition: color 0.3s; &[data-color="primary"]&[data-style="outlined"] { - color: rgb(var(--color-primary)); + color: var(--color-primary); } &[data-color="secondary"]&[data-style="outlined"] { - color: rgb(var(--color-secondary)); + color: var(--color-secondary); } &[data-color="success"]&[data-style="outlined"] { - color: rgb(var(--color-success)); + color: var(--color-success); } &[data-color="error"]&[data-style="outlined"] { - color: rgb(var(--color-error)); + color: var(--color-error); } &[data-color="info"]&[data-style="outlined"] { - color: rgb(var(--color-info)); + color: var(--color-info); } &[data-color="warning"]&[data-style="outlined"] { - color: rgb(var(--color-warning)); + color: var(--color-warning); } &[data-size="small"] { @@ -305,13 +305,13 @@ pub fn Button(props: &Props) -> Html { } &[data-style="outlined"] { - color: rgb(var(--color-primary)); + color: var(--color-primary); } &[data-style="outlined"]&[data-state="active"] { - color: rgb(var(--color-button-text)); + color: var(--color-button-text); } &[data-style="basic"] { - color: rgb(var(--color-button-text)); + color: var(--color-button-text); } "#)} diff --git a/packages/components/src/form/button/button_group.rs b/packages/components/src/form/button/button_group.rs index 2279254..5c5e7da 100644 --- a/packages/components/src/form/button/button_group.rs +++ b/packages/components/src/form/button/button_group.rs @@ -51,7 +51,7 @@ pub fn ButtonGroup(props: &Props) -> Html { display: flex; flex-direction: row; "#)}> - { @@ -61,20 +61,20 @@ pub fn ButtonGroup(props: &Props) -> Html { html! {} } } - + {props.children.iter().skip(1).take(props.children.len() - 2).map(|child| html! { - {{ let child: Html = child.clone().into(); child }} - + }).collect::()} - { @@ -84,7 +84,7 @@ pub fn ButtonGroup(props: &Props) -> Html { html! {} } } - + }, } diff --git a/packages/macro-types/src/register.rs b/packages/macro-types/src/register.rs index dbc8457..4655da5 100644 --- a/packages/macro-types/src/register.rs +++ b/packages/macro-types/src/register.rs @@ -90,7 +90,7 @@ where
{html_raw}
- + ")) diff --git a/packages/theme/src/components/form/button.rs b/packages/theme/src/components/form/button.rs index 18721fd..935d9a6 100644 --- a/packages/theme/src/components/form/button.rs +++ b/packages/theme/src/components/form/button.rs @@ -12,12 +12,12 @@ pub enum BorderRadiusType { } #[derive(Debug, PartialEq, Clone)] -pub struct ContextState { +pub struct ComponentContextState { pub border_radius_type: BorderRadiusType, } #[derive(Properties, Debug, PartialEq)] -pub struct ContextProps { +pub struct ComponentContextProps { #[prop_or(SizeType::Medium)] pub size: SizeType, #[prop_or(ColorType::Primary)] @@ -31,17 +31,17 @@ pub struct ContextProps { pub children: Children, } -pub type ContextProviderType = UseStateHandle; +pub type ComponentContextProviderType = UseStateHandle; #[function_component] -pub fn ContextShell(props: &ContextProps) -> Html { - let ctx = use_state(|| ContextState { +pub fn ComponentContextShell(props: &ComponentContextProps) -> Html { + let ctx = use_state(|| ComponentContextState { border_radius_type: props.border_radius_type, }); html! { - context={ctx.clone()}> + context={ctx.clone()}> {props.children.clone() } - > + > } } diff --git a/packages/theme/src/context.rs b/packages/theme/src/context.rs new file mode 100644 index 0000000..bdacb0a --- /dev/null +++ b/packages/theme/src/context.rs @@ -0,0 +1,111 @@ +use yuuka::derive_struct; + +use yew::prelude::*; + +use crate::{ + prelude::element::designs::color::COLOR_MAP, + types::{ColorLevel, ColorMap}, +}; + +derive_struct!(pub Theme { color: ColorMap = COLOR_MAP.clone() }); + +#[derive(Properties, Debug, PartialEq)] +pub struct ThemeContextProviderProps { + pub context: Theme, + + #[prop_or_default] + pub children: Children, +} + +#[function_component] +pub fn ThemeContextShell(props: &ThemeContextProviderProps) -> Html { + html! { + context={props.context.clone()}> + + + {props.children.clone() } + > + } +} diff --git a/packages/theme/src/global_states.rs b/packages/theme/src/global_states.rs deleted file mode 100644 index 7f66252..0000000 --- a/packages/theme/src/global_states.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::collections::HashMap; - -use yew::prelude::*; - -pub trait Theme: Clone + PartialEq + Default + 'static { - fn get_color(&self, t: crate::types::ColorType) -> crate::types::Color; -} - -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct ThemeContext { - pub theme: T, - pub state: HashMap, -} - -#[derive(Properties, Debug, PartialEq)] -pub struct ThemeContextProviderProps { - #[prop_or_default] - pub children: Children, -} - -pub type ThemeContextProviderType = UseStateHandle>; - -#[function_component] -fn Injector() -> Html { - use crate::types::ColorType; - - let app_states = use_context::>().unwrap(); - let theme_raw = format!( - r#" - :root {{ - --color-primary: {}; - --color-secondary: {}; - - --color-success: {}; - --color-warning: {}; - --color-error: {}; - --color-info: {}; - }} - - - * {{ - margin: 0; - padding: 0; - box-sizing: border-box; - }} - - body {{ - font-family: 'PingFang SC', 'Helvetica Neue', 'Microsoft YaHei', sans-serif; - background-color: rgb(var(--color-background)); - color: rgb(var(--color-primary-text)); - }} - "#, - app_states.theme.get_color(ColorType::Primary).to_rgb_str(), - app_states - .theme - .get_color(ColorType::Secondary) - .to_rgb_str(), - app_states.theme.get_color(ColorType::Success).to_rgb_str(), - app_states.theme.get_color(ColorType::Warning).to_rgb_str(), - app_states.theme.get_color(ColorType::Error).to_rgb_str(), - app_states.theme.get_color(ColorType::Info).to_rgb_str(), - ); - - html! { - <> - - - } -} - -#[function_component] -pub fn ThemeContextShell(props: &ThemeContextProviderProps) -> Html { - let ctx = use_state(|| ThemeContext { - theme: T::default(), - state: HashMap::new(), - }); - - html! { - > context={ctx.clone()}> - /> - {props.children.clone() } - >> - } -} diff --git a/packages/theme/src/lib.rs b/packages/theme/src/lib.rs index d5034f0..b6dd376 100644 --- a/packages/theme/src/lib.rs +++ b/packages/theme/src/lib.rs @@ -1,4 +1,4 @@ pub mod components; -pub mod global_states; +pub mod context; pub mod prelude; pub mod types; diff --git a/packages/theme/src/types/color.rs b/packages/theme/src/types/color.rs index 2ff1a40..dd93a68 100644 --- a/packages/theme/src/types/color.rs +++ b/packages/theme/src/types/color.rs @@ -11,6 +11,26 @@ pub enum ColorType { Warning, } +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] +pub enum ColorLevel { + #[default] + Full, + Most, + Half, + Less, +} + +impl Into for ColorLevel { + fn into(self) -> f64 { + match self { + ColorLevel::Full => 1.0, + ColorLevel::Most => 0.8, + ColorLevel::Half => 0.5, + ColorLevel::Less => 0.2, + } + } +} + #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct ColorMap { pub primary: Color, @@ -44,19 +64,21 @@ impl Color { pub fn to_rgb_str(&self) -> String { format!( - "rgb({:.3},{:.3},{:.3})", - self.red * 256.0, - self.green * 256.0, - self.blue * 256.0 + "rgb({:.0},{:.0},{:.0})", + self.red * 256., + self.green * 256., + self.blue * 256. ) } - pub fn to_rgba_str(&self, alpha: f32) -> String { + pub fn to_rgba_str(&self, alpha: ColorLevel) -> String { + let alpha: f64 = alpha.into(); + format!( - "rgba({:.3},{:.3},{:.3},{:.3})", - self.red * 256.0, - self.green * 256.0, - self.blue * 256.0, + "rgba({:.0},{:.0},{:.0},{:.1})", + self.red * 256., + self.green * 256., + self.blue * 256., alpha ) } @@ -64,9 +86,9 @@ impl Color { pub fn to_rgb_str_hex(&self) -> String { format!( "#{:02x}{:02x}{:02x}", - (self.red * 256.0) as u8, - (self.green * 256.0) as u8, - (self.blue * 256.0) as u8 + (self.red * 256.) as u8, + (self.green * 256.) as u8, + (self.blue * 256.) as u8 ) } } diff --git a/website/Cargo.toml b/website/Cargo.toml index 8399b62..a9f172a 100644 --- a/website/Cargo.toml +++ b/website/Cargo.toml @@ -46,6 +46,7 @@ yew-router = { workspace = true } [dev-dependencies] hikari-website = { path = "." } hikari-boot = { path = "../packages/boot" } +hikari-components = { path = "../packages/components" } env_logger = { workspace = true } tokio = { workspace = true } diff --git a/website/examples/dev/render.rs b/website/examples/dev/render.rs index 08f6e94..546abaa 100644 --- a/website/examples/dev/render.rs +++ b/website/examples/dev/render.rs @@ -15,21 +15,6 @@ pub async fn html(url: String) -> Result -
- - - {raw} -
-"# - ); { let mut headers = HeaderMap::new(); diff --git a/website/src/app.rs b/website/src/app.rs index 4b3cc7d..cd73050 100644 --- a/website/src/app.rs +++ b/website/src/app.rs @@ -4,8 +4,7 @@ use yew_router::prelude::*; use crate::pages::*; use hikari_boot::{DeclType, DeriveApplication, DeriveRoutes, RoutesOutsideProps}; -use hikari_components::prelude::element::designs::color::COLOR_MAP; -use hikari_theme::types::ColorMap; +use hikari_theme::context::{Theme, ThemeContextShell}; #[derive(PartialEq, Clone, Debug, DeriveRoutes, Routable)] pub enum Routes { @@ -27,9 +26,7 @@ pub enum Routes { } derive_struct!(AppStates { - theme: { - color: ColorMap = COLOR_MAP.clone() - } + theme: Theme, data: enum PageData { Portal Guide { id: String, raw: String } @@ -49,47 +46,10 @@ impl DeclType for App { type AppStates = AppStates; fn decl_render_outside(props: &RoutesOutsideProps) -> yew::HtmlResult { - let theme_raw = format!( - r#" - :root {{ - --color-primary: {}; - --color-secondary: {}; - - --color-error: {}; - --color-warning: {}; - --color-success: {}; - --color-info: {}; - }} - - - * {{ - margin: 0; - padding: 0; - box-sizing: border-box; - }} - - body {{ - font-family: 'PingFang SC', 'Helvetica Neue', 'Microsoft YaHei', sans-serif; - background-color: rgb(var(--color-background)); - color: rgb(var(--color-primary-text)); - }} - "#, - props.states.theme.color.primary.to_rgb_str(), - props.states.theme.color.secondary.to_rgb_str(), - props.states.theme.color.error.to_rgb_str(), - props.states.theme.color.warning.to_rgb_str(), - props.states.theme.color.success.to_rgb_str(), - props.states.theme.color.info.to_rgb_str(), - ); - Ok(yew::html! { - <> - - + {props.children.clone()} - + }) } } diff --git a/website/src/pages/component.rs b/website/src/pages/component.rs index 06cacb6..dd7cf37 100644 --- a/website/src/pages/component.rs +++ b/website/src/pages/component.rs @@ -1,6 +1,9 @@ use stylist::yew::styled_component; use yew::prelude::*; +use hikari_components::form::Button; +use hikari_theme::types::ColorType; + #[derive(Properties, Debug, PartialEq)] pub struct Props { #[prop_or_default] @@ -13,6 +16,15 @@ pub fn Component(props: &Props) -> Html { <>

{"Component"}

{format!("Component {}", props.id)}

+ + } }