From ae4a69fd157e7d7f8807c265097ecbbda4990bc3 Mon Sep 17 00:00:00 2001 From: luoxiao Date: Thu, 23 May 2024 14:48:06 +0800 Subject: [PATCH] reactor: radio --- demo_markdown/docs/radio/mod.md | 20 ++------ thaw/src/checkbox/mod.rs | 6 +-- thaw/src/radio/mod.rs | 68 ++++++++++++++++---------- thaw/src/radio/radio.css | 87 ++++++++++++++++++++++++--------- thaw/src/radio/radio_group.rs | 14 ++++-- thaw/src/radio/radio_item.rs | 39 --------------- thaw/src/theme/color.rs | 6 +++ 7 files changed, 128 insertions(+), 112 deletions(-) delete mode 100644 thaw/src/radio/radio_item.rs diff --git a/demo_markdown/docs/radio/mod.md b/demo_markdown/docs/radio/mod.md index 87d5b84..d3b6889 100644 --- a/demo_markdown/docs/radio/mod.md +++ b/demo_markdown/docs/radio/mod.md @@ -1,26 +1,12 @@ # Radio ```rust demo -let value = create_rw_signal(false); - -view! { - "Click" -} -``` - -### Group - -```rust demo -let value = create_rw_signal(None); +let value = RwSignal::new(None); view! { - - "Apple" - - - "Orange" - + +
"value: " {move || format!("{:?}", value.get())} diff --git a/thaw/src/checkbox/mod.rs b/thaw/src/checkbox/mod.rs index b3ece84..acabd1e 100644 --- a/thaw/src/checkbox/mod.rs +++ b/thaw/src/checkbox/mod.rs @@ -25,7 +25,7 @@ pub fn Checkbox( }; view! { -
-
+ + } } diff --git a/thaw/src/radio/mod.rs b/thaw/src/radio/mod.rs index d281355..048af83 100644 --- a/thaw/src/radio/mod.rs +++ b/thaw/src/radio/mod.rs @@ -1,45 +1,61 @@ mod radio_group; -mod radio_item; pub use radio_group::RadioGroup; -pub use radio_item::RadioItem; -use crate::{theme::use_theme, Theme}; use leptos::*; -use thaw_utils::{class_list, mount_style, Model, OptionalProp}; +use radio_group::RadioGroupInjection; +use thaw_utils::{class_list, mount_style, OptionalProp}; #[component] pub fn Radio( - #[prop(optional, into)] value: Model, #[prop(optional, into)] class: OptionalProp>, - #[prop(optional)] children: Option, + #[prop(optional, into)] value: String, + #[prop(optional, into)] label: MaybeProp, ) -> impl IntoView { - let theme = use_theme(Theme::light); mount_style("radio", include_str!("./radio.css")); - let css_vars = create_memo(move |_| { - let mut css_vars = String::new(); - theme.with(|theme| { - let bg_color = theme.common.color_primary.clone(); - css_vars.push_str(&format!("--thaw-background-color-checked: {bg_color};")); - }); + let id = uuid::Uuid::new_v4().to_string(); + let group = RadioGroupInjection::use_(); + let item_value = StoredValue::new(value); - css_vars + let checked = Memo::new({ + let group = group.clone(); + move |_| { + item_value.with_value(|value| { + group + .0 + .with(|group_value| group_value.as_ref() == Some(value)) + }) + } }); - view! { -
- -
-
{children.map(|children| children())}
-
+ + + { + move || if let Some(label) = label.get() { + view! { + + }.into() + } else { + None + } + } + } } diff --git a/thaw/src/radio/radio.css b/thaw/src/radio/radio.css index 31dbd64..785bf92 100644 --- a/thaw/src/radio/radio.css +++ b/thaw/src/radio/radio.css @@ -1,42 +1,81 @@ .thaw-radio { display: inline-flex; - align-items: center; - cursor: pointer; + position: relative; } .thaw-radio__input { - width: 0; - height: 0; + position: absolute; + left: 0px; + top: 0px; + width: calc(16px + 2 * var(--spacingHorizontalS)); + height: 100%; + box-sizing: border-box; + margin: 0px; opacity: 0; } -.thaw-radio__dot { - display: inline-block; +.thaw-radio__input:enabled { + cursor: pointer; +} + +.thaw-radio__indicator { position: relative; - width: 14px; - height: 14px; - border: 1px solid #ddd; - border-radius: 50%; + width: 16px; + height: 16px; + font-size: 12px; + box-sizing: border-box; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + border: var(--strokeWidthThin) solid; + border-radius: var(--borderRadiusCircular); + margin: var(--spacingVerticalS) var(--spacingHorizontalS); + fill: currentcolor; + pointer-events: none; } -.thaw-radio:hover .thaw-radio__dot, -.thaw-radio--checked .thaw-radio__dot { - border-color: var(--thaw-background-color-checked); +.thaw-radio__input:enabled:not(:checked) ~ .thaw-radio__indicator { + border-color: var(--colorNeutralStrokeAccessible); } -.thaw-radio--checked .thaw-radio__dot::before { - content: ""; +.thaw-radio__input:checked ~ .thaw-radio__indicator { + border-color: var(--colorCompoundBrandStroke); + color: var(--colorCompoundBrandForeground1); +} + +.thaw-radio__indicator::after { position: absolute; - top: 3px; - bottom: 3px; - left: 3px; - right: 3px; - background-color: var(--thaw-background-color-checked); - border-radius: 50%; + width: 16px; + height: 16px; + border-radius: var(--borderRadiusCircular); + transform: scale(0.625); + background-color: currentcolor; +} + +.thaw-radio__input:checked ~ .thaw-radio__indicator::after { + content: ""; } .thaw-radio__label { - display: inline-block; - padding: 0 6px; - user-select: none; + margin-bottom: calc((16px - var(--lineHeightBase300)) / 2); + margin-top: calc((16px - var(--lineHeightBase300)) / 2); + align-self: center; + padding-bottom: var(--spacingVerticalS); + padding-top: var(--spacingVerticalS); + padding-left: var(--spacingHorizontalXS); + padding-right: var(--spacingHorizontalS); + line-height: var(--lineHeightBase300); + font-size: var(--fontSizeBase300); + font-family: var(--fontFamilyBase); + color: var(--colorNeutralForeground1); +} + +.thaw-radio__input:enabled:not(:checked) ~ .thaw-radio__label { + color: var(--colorNeutralForeground3); +} + +.thaw-radio__input:enabled ~ .thaw-radio__label { + cursor: pointer; } diff --git a/thaw/src/radio/radio_group.rs b/thaw/src/radio/radio_group.rs index 0827c39..5206bed 100644 --- a/thaw/src/radio/radio_group.rs +++ b/thaw/src/radio/radio_group.rs @@ -6,12 +6,20 @@ pub fn RadioGroup( #[prop(optional, into)] value: Model>, children: Children, ) -> impl IntoView { - view! { } + view! { + +
+ {children()} +
+
+ } } #[derive(Clone)] pub(crate) struct RadioGroupInjection(pub Model>); -pub(crate) fn use_radio_group() -> RadioGroupInjection { - expect_context() +impl RadioGroupInjection { + pub fn use_() -> RadioGroupInjection { + expect_context() + } } diff --git a/thaw/src/radio/radio_item.rs b/thaw/src/radio/radio_item.rs deleted file mode 100644 index 10dd1ce..0000000 --- a/thaw/src/radio/radio_item.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::radio::{radio_group::use_radio_group, Radio}; -use leptos::*; -use thaw_utils::OptionalProp; - -#[component] -pub fn RadioItem( - #[prop(optional, into)] class: OptionalProp>, - #[prop(into)] key: String, - #[prop(optional)] children: Option, -) -> impl IntoView { - let radio_group_value = use_radio_group().0; - let checked = RwSignal::new(false); - let item_key = store_value(key); - - let is_checked = Memo::new(move |_| { - radio_group_value.with(|value| item_key.with_value(|key| value.as_ref() == Some(key))) - }); - - Effect::new(move |prev| { - let checked = checked.get(); - if prev.is_some() { - if !is_checked.get_untracked() { - radio_group_value.set(Some(item_key.get_value())) - } - } - - checked - }); - - if let Some(children) = children { - view! { - - {children()} - - } - } else { - view! { } - } -} diff --git a/thaw/src/theme/color.rs b/thaw/src/theme/color.rs index aa07a79..ab6414f 100644 --- a/thaw/src/theme/color.rs +++ b/thaw/src/theme/color.rs @@ -35,6 +35,8 @@ pub struct ColorTheme { pub color_neutral_stroke_accessible_hover: String, pub color_neutral_stroke_accessible_pressed: String, + pub color_compound_brand_foreground_1: String, + pub color_compound_brand_background: String, pub color_compound_brand_background_hover: String, pub color_compound_brand_background_pressed: String, @@ -90,6 +92,8 @@ impl ColorTheme { color_neutral_stroke_accessible_hover: "#575757".into(), color_neutral_stroke_accessible_pressed: "#4d4d4d".into(), + color_compound_brand_foreground_1: "#0f6cbd".into(), + color_compound_brand_background: "#0f6cbd".into(), color_compound_brand_background_hover: "#115ea3".into(), color_compound_brand_background_pressed: "#0f548c".into(), @@ -145,6 +149,8 @@ impl ColorTheme { color_neutral_stroke_accessible_hover: "#bdbdbd".into(), color_neutral_stroke_accessible_pressed: "#b3b3b3".into(), + color_compound_brand_foreground_1: "#479ef5".into(), + color_compound_brand_background: "#479ef5".into(), color_compound_brand_background_hover: "#62abf5".into(), color_compound_brand_background_pressed: "#2886de".into(),