From 21e3d6e455ad54908e625e44577d530bd2c7f867 Mon Sep 17 00:00:00 2001 From: lizidev Date: Mon, 18 Aug 2025 11:27:04 +0800 Subject: [PATCH 1/9] feat: ColorPicker adds disabled prop --- thaw/src/color_picker/color-picker.css | 4 ++++ thaw/src/color_picker/docs/mod.md | 23 ++++++++++++++++++----- thaw/src/color_picker/mod.rs | 7 +++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/thaw/src/color_picker/color-picker.css b/thaw/src/color_picker/color-picker.css index 15378ad0..18ccf705 100644 --- a/thaw/src/color_picker/color-picker.css +++ b/thaw/src/color_picker/color-picker.css @@ -28,6 +28,10 @@ height: 100%; } +.thaw-color-picker-trigger--disabled { + cursor: not-allowed; +} + div.thaw-color-picker-popover { width: 240px; padding: var(--spacingVerticalM) var(--spacingHorizontalM); diff --git a/thaw/src/color_picker/docs/mod.md b/thaw/src/color_picker/docs/mod.md index d352c1c7..9925d486 100644 --- a/thaw/src/color_picker/docs/mod.md +++ b/thaw/src/color_picker/docs/mod.md @@ -46,10 +46,23 @@ view! { } ``` +### Disabled + +```rust demo +use palette::Srgb; + +let value = RwSignal::new(Color::from(Srgb::new(0.0, 0.0, 0.0))); + +view! { + +} +``` + ### ColorPicker Props -| Name | Type | Default | Desciption | -| ----- | ------------------------- | ------------------------- | -------------------- | -| class | `MaybeProp` | `Default::default()` | | -| value | `Model` | `Default::default()` | Value of the picker. | -| size | `Signal` | `ColorPickerSize::Medium` | Size of the picker. | +| Name | Type | Default | Desciption | +| -------- | ------------------------- | ------------------------- | ------------------------------------ | +| class | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Whether to disable the color picker. | +| value | `Model` | `Default::default()` | Value of the picker. | +| size | `Signal` | `ColorPickerSize::Medium` | Size of the picker. | diff --git a/thaw/src/color_picker/mod.rs b/thaw/src/color_picker/mod.rs index 43b7d9e0..37192088 100644 --- a/thaw/src/color_picker/mod.rs +++ b/thaw/src/color_picker/mod.rs @@ -19,6 +19,9 @@ pub fn ColorPicker( /// Size of the picker. #[prop(optional, into)] size: Signal, + /// Whether to disable the color picker. + #[prop(optional, into)] + disabled: Signal, ) -> impl IntoView { mount_style("color-picker", include_str!("./color-picker.css")); let hue = RwSignal::new(0f32); @@ -104,6 +107,9 @@ pub fn ColorPicker( let trigger_ref = NodeRef::::new(); let popover_ref = NodeRef::::new(); let show_popover = move |_| { + if disabled.get() { + return; + } is_show_popover.set(true); }; @@ -140,6 +146,7 @@ pub fn ColorPicker(
Date: Mon, 18 Aug 2025 14:06:13 +0800 Subject: [PATCH 2/9] feat: DatePicker adds disabled prop --- thaw/src/date_picker/docs/mod.md | 9 +++++++++ thaw/src/date_picker/mod.rs | 7 +++++++ thaw/src/input/input.css | 2 ++ 3 files changed, 18 insertions(+) diff --git a/thaw/src/date_picker/docs/mod.md b/thaw/src/date_picker/docs/mod.md index 7d10db1b..3dcfe605 100644 --- a/thaw/src/date_picker/docs/mod.md +++ b/thaw/src/date_picker/docs/mod.md @@ -25,12 +25,21 @@ view! { } ``` +### Disabled + +```rust demo +view! { + +} +``` + ### DatePicker Props | Name | Type | Default | Desciption | | --- | --- | --- | --- | | class | `MaybeProp` | `Default::default()` | | | id | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Whether the date picker is disabled. | | name | `MaybeProp` | `Default::default()` | A string specifying a name for the input control. This name is submitted along with the control's value when the form data is submitted. | | rules | `Vec>` | `vec![]` | The rules to validate Field. | | value | `OptionModel` | `Default::default()` | Set the date picker value. | diff --git a/thaw/src/date_picker/mod.rs b/thaw/src/date_picker/mod.rs index 11fd894c..d3c35b9a 100644 --- a/thaw/src/date_picker/mod.rs +++ b/thaw/src/date_picker/mod.rs @@ -18,6 +18,9 @@ use thaw_utils::{ pub fn DatePicker( #[prop(optional, into)] class: MaybeProp, #[prop(optional, into)] id: MaybeProp, + /// Whether the date picker is disabled. + #[prop(optional, into)] + disabled: Signal, /// A string specifying a name for the input control. /// This name is submitted along with the control's value when the form data is submitted. #[prop(optional, into)] @@ -92,6 +95,9 @@ pub fn DatePicker( }; let open_panel = move || { + if disabled.get() { + return; + } if is_show_panel.get() { return; } @@ -112,6 +118,7 @@ pub fn DatePicker( .thaw-input__prefix, +.thaw-input--disabled > .thaw-input__suffix, .thaw-input--disabled > .thaw-input__input::placeholder { color: var(--colorNeutralForegroundDisabled); } From 53abe1ced7f1f2d2c0f80e33f7c2383ecceab7d4 Mon Sep 17 00:00:00 2001 From: lizidev Date: Mon, 18 Aug 2025 14:52:15 +0800 Subject: [PATCH 3/9] feat: RadioGroup adds disabled prop --- thaw/src/radio/docs/mod.md | 14 ++++++++++++++ thaw/src/radio/mod.rs | 1 + thaw/src/radio/radio.css | 14 ++++++++++++-- thaw/src/radio/radio_group.rs | 7 ++++++- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/thaw/src/radio/docs/mod.md b/thaw/src/radio/docs/mod.md index bf61d8c9..f0470a39 100644 --- a/thaw/src/radio/docs/mod.md +++ b/thaw/src/radio/docs/mod.md @@ -24,6 +24,19 @@ view! { } ``` +## Disabled + +RadioGroup can be disabled, which disables all Radio items inside. + +```rust demo +view! { + + + + +} +``` + ### Radio Props | Name | Type | Default | Description | @@ -38,6 +51,7 @@ view! { | --- | --- | --- | --- | | class | `MaybeProp` | `Default::default()` | | | id | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Disable all Radio items in this group. | | name | `MaybeProp` | `Default::default()` | A string specifying a name for the input control. This name is submitted along with the control's value when the form data is submitted. | | rules | `Vec` | `vec![]` | The rules to validate Field. | | value | `OptionModel` | `Default::default()` | The selected Radio item in this group. | diff --git a/thaw/src/radio/mod.rs b/thaw/src/radio/mod.rs index 2e58cf07..35ef36f2 100644 --- a/thaw/src/radio/mod.rs +++ b/thaw/src/radio/mod.rs @@ -44,6 +44,7 @@ pub fn Radio( class="thaw-radio__input" type="radio" id=id.clone() + disabled=group.disabled name=group.name value=item_value.get_value() prop:checked=move || checked.get() diff --git a/thaw/src/radio/radio.css b/thaw/src/radio/radio.css index 509ce67b..5aecbdf1 100644 --- a/thaw/src/radio/radio.css +++ b/thaw/src/radio/radio.css @@ -50,11 +50,11 @@ color: var(--colorCompoundBrandForeground1); } -.thaw-radio__input:hover:checked ~ .thaw-radio__indicator { +.thaw-radio__input:hover:checked:not(:disabled) ~ .thaw-radio__indicator { color: var(--colorCompoundBrandForeground1Hover); } -.thaw-radio__input:hover:active ~ .thaw-radio__indicator { +.thaw-radio__input:hover:active:not(:disabled) ~ .thaw-radio__indicator { color: var(--colorCompoundBrandForeground1Pressed); } @@ -71,6 +71,11 @@ content: ""; } +.thaw-radio__input:disabled ~ .thaw-radio__indicator { + border-color: var(--colorNeutralStrokeDisabled); + color: var(--colorNeutralForegroundDisabled); +} + .thaw-radio__label { margin-bottom: calc((16px - var(--lineHeightBase300)) / 2); margin-top: calc((16px - var(--lineHeightBase300)) / 2); @@ -100,3 +105,8 @@ .thaw-radio__input:enabled ~ .thaw-radio__label { cursor: pointer; } + +.thaw-radio__input:disabled ~ .thaw-radio__label { + color: var(--colorNeutralForegroundDisabled); + cursor: default; +} diff --git a/thaw/src/radio/radio_group.rs b/thaw/src/radio/radio_group.rs index d65bc17e..54f20f28 100644 --- a/thaw/src/radio/radio_group.rs +++ b/thaw/src/radio/radio_group.rs @@ -7,6 +7,10 @@ use thaw_utils::{class_list, OptionModel}; pub fn RadioGroup( #[prop(optional, into)] class: MaybeProp, #[prop(optional, into)] id: MaybeProp, + /// Disable all Radio items in this group. + #[prop(optional, into)] + disabled: Signal, + /// The rules to validate Field. #[prop(optional, into)] rules: Vec, /// The selected Radio item in this group. #[prop(optional, into)] @@ -32,7 +36,7 @@ pub fn RadioGroup( }); view! { - +
{children()}
@@ -44,6 +48,7 @@ pub fn RadioGroup( pub(crate) struct RadioGroupInjection { pub value: OptionModel, pub name: Signal, + pub disabled: Signal, } impl RadioGroupInjection { From 2b21ac07360ebdc7bc3329eaf9ad588856efb024 Mon Sep 17 00:00:00 2001 From: lizidev Date: Tue, 19 Aug 2025 14:34:32 +0800 Subject: [PATCH 4/9] feat: Slider adds disabled prop --- thaw/src/slider/docs/mod.md | 26 +++++++++++++++++++ thaw/src/slider/docs/range-slider.md | 26 ++++++++++++++++++- thaw/src/slider/range_slider/mod.rs | 17 +++++++++++- thaw/src/slider/range_slider/range-slider.css | 22 ++++++++++++++++ thaw/src/slider/slider/mod.rs | 5 ++++ thaw/src/slider/slider/slider.css | 11 ++++++++ 6 files changed, 105 insertions(+), 2 deletions(-) diff --git a/thaw/src/slider/docs/mod.md b/thaw/src/slider/docs/mod.md index acbcdc1c..ab19f9f7 100644 --- a/thaw/src/slider/docs/mod.md +++ b/thaw/src/slider/docs/mod.md @@ -31,6 +31,31 @@ view! { } ``` +### Disabled + +A disabled slider will not change or fire events on click or keyboard press. + +```rust demo +let value = RwSignal::new(0.0); + +view! { + + + + + "0" + + + "5" + + + "10" + + + +} +``` + ## Slider Label ```rust demo @@ -58,6 +83,7 @@ view! { | class | `MaybeProp` | `Default::default()` | | | style | `MaybeProp` | `Default::default()` | | | id | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Whether the slider is disabled. | | name | `MaybeProp` | `Default::default()` | A string specifying a name for the input control. This name is submitted along with the control's value when the form data is submitted. | | rules | `Vec` | `vec![]` | The rules to validate Field. | | value | `Model` | `0` | The current value of the controlled Slider. | diff --git a/thaw/src/slider/docs/range-slider.md b/thaw/src/slider/docs/range-slider.md index 78d35969..d3873bf6 100644 --- a/thaw/src/slider/docs/range-slider.md +++ b/thaw/src/slider/docs/range-slider.md @@ -34,13 +34,36 @@ view! { } ``` +### Disabled + +```rust demo +let value = RwSignal::new((6.0, 8.0)); + +view! { + + + + + "0" + + + "5" + + + "10" + + + +} +``` + ### SliderLabel ```rust demo let value = RwSignal::new((0.0, 1.0)); view! { - + "0" @@ -60,6 +83,7 @@ view! { | --- | --- | --- | --- | | class | `MaybeProp` | `Default::default()` | | | style | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Whether the slider is disabled. | | value | `Model<(f64, f64)>` | `(0.0, 0.0)` | The current value of the controlled Slider. | | min | `Signal` | `0` | Min value of the slider. | | max | `Signal` | `100` | Max value of the slider. | diff --git a/thaw/src/slider/range_slider/mod.rs b/thaw/src/slider/range_slider/mod.rs index f67d3b9f..521d291e 100644 --- a/thaw/src/slider/range_slider/mod.rs +++ b/thaw/src/slider/range_slider/mod.rs @@ -7,7 +7,12 @@ use thaw_utils::{class_list, mount_style, Model}; pub fn RangeSlider( #[prop(optional, into)] class: MaybeProp, #[prop(optional, into)] style: MaybeProp, - #[prop(optional, into)] value: Model<(f64, f64)>, + /// Whether the slider is disabled. + #[prop(optional, into)] + disabled: Signal, + /// The current value of the controlled Slider. + #[prop(optional, into)] + value: Model<(f64, f64)>, /// Min value of the slider. #[prop(default = 0f64.into(), into)] min: Signal, @@ -111,6 +116,9 @@ pub fn RangeSlider( }; let on_click = move |e: web_sys::MouseEvent| { + if disabled.get() { + return; + } if let Some(rail_el) = rail_ref.get_untracked() { let min = min.get_untracked(); let max = max.get_untracked(); @@ -210,11 +218,17 @@ pub fn RangeSlider( }; let on_left_mousedown = move |_| { + if disabled.get() { + return; + } left_mousemove.set_value(true); on_mousemove(); }; let on_right_mousedown = move |_| { + if disabled.get() { + return; + } right_mousemove.set_value(true); on_mousemove(); }; @@ -225,6 +239,7 @@ pub fn RangeSlider(
, #[prop(optional, into)] style: MaybeProp, #[prop(optional, into)] id: MaybeProp, + /// Whether the slider is disabled. + #[prop(optional, into)] + disabled: Signal, /// A string specifying a name for the input control. /// This name is submitted along with the control's value when the form data is submitted. #[prop(optional, into)] @@ -106,12 +109,14 @@ pub fn Slider(
Date: Tue, 19 Aug 2025 15:43:30 +0800 Subject: [PATCH 5/9] feat: Switch adds disabled prop --- thaw/src/switch/docs/mod.md | 24 ++++++++++++++++++++++++ thaw/src/switch/mod.rs | 4 ++++ thaw/src/switch/switch.css | 22 ++++++++++++++++++++++ thaw/src/theme/color.rs | 4 ++++ 4 files changed, 54 insertions(+) diff --git a/thaw/src/switch/docs/mod.md b/thaw/src/switch/docs/mod.md index 910f9faa..6bc2c3fd 100644 --- a/thaw/src/switch/docs/mod.md +++ b/thaw/src/switch/docs/mod.md @@ -8,12 +8,36 @@ view! { } ``` +### Disabled + +A Switch can be disabled. + +```rust demo +view! { + + + + +} +``` + +### Label + +```rust demo +let checked = RwSignal::new(false); + +view! { + +} +``` + ### Switch Props | Name | Type | Default | Description | | --- | --- | --- | --- | | class | `MaybeProp` | `Default::default()` | | | id | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Whether to disable the switch. | | name | `MaybeProp` | `Default::default()` | A string specifying a name for the input control. This name is submitted along with the control's value when the form data is submitted. | | value | `MaybeProp` | `Default::default()` | A string specifying the value for the input control. | | rules | `Vec` | `vec![]` | The rules to validate Field. | diff --git a/thaw/src/switch/mod.rs b/thaw/src/switch/mod.rs index e1f5b14f..575e7c8e 100644 --- a/thaw/src/switch/mod.rs +++ b/thaw/src/switch/mod.rs @@ -7,6 +7,9 @@ use thaw_utils::{class_list, mount_style, Model}; pub fn Switch( #[prop(optional, into)] class: MaybeProp, #[prop(optional, into)] id: MaybeProp, + /// Whether to disable the switch. + #[prop(optional, into)] + disabled: Signal, /// A string specifying a name for the input control. /// This name is submitted along with the control's value when the form data is submitted. #[prop(optional, into)] @@ -48,6 +51,7 @@ pub fn Switch(
svg { display: inline; line-height: 0; @@ -81,3 +98,8 @@ .thaw-switch__input:enabled:not(:checked) ~ .thaw-switch__label { color: var(--colorNeutralForeground1); } + +.thaw-switch__input:disabled ~ .thaw-switch__label { + cursor: default; + color: var(--colorNeutralForegroundDisabled); +} \ No newline at end of file diff --git a/thaw/src/theme/color.rs b/thaw/src/theme/color.rs index a906c3b0..7513ff7a 100644 --- a/thaw/src/theme/color.rs +++ b/thaw/src/theme/color.rs @@ -117,10 +117,12 @@ pub struct ColorTheme { color_subtle_background: String, color_subtle_background_hover: String, color_subtle_background_pressed: String, + color_transparent_background: String, color_transparent_background_hover: String, color_transparent_background_pressed: String, color_transparent_stroke: String, + color_transparent_stroke_disabled: String, shadow4: String, shadow8: String, @@ -318,6 +320,7 @@ impl ColorTheme { color_transparent_background_hover: "transparent".into(), color_transparent_background_pressed: "transparent".into(), color_transparent_stroke: "transparent".into(), + color_transparent_stroke_disabled: "transparent".into(), shadow4: "0 0 2px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.14)".into(), shadow8: "0 0 2px rgba(0,0,0,0.12), 0 4px 8px rgba(0,0,0,0.14)".into(), @@ -445,6 +448,7 @@ impl ColorTheme { color_transparent_background_hover: "transparent".into(), color_transparent_background_pressed: "transparent".into(), color_transparent_stroke: "transparent".into(), + color_transparent_stroke_disabled: "transparent".into(), shadow4: "0 0 2px rgba(0,0,0,0.24), 0 2px 4px rgba(0,0,0,0.28)".into(), shadow8: "0 0 2px rgba(0,0,0,0.24), 0 4px 8px rgba(0,0,0,0.28)".into(), From 8ff783d69d350f1755eeb8922e28307d7548d0ae Mon Sep 17 00:00:00 2001 From: lizidev Date: Tue, 19 Aug 2025 16:11:28 +0800 Subject: [PATCH 6/9] feat: TimePicker adds disabled prop --- thaw/src/time_picker/docs/mod.md | 21 ++++++++++++++++++--- thaw/src/time_picker/mod.rs | 7 +++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/thaw/src/time_picker/docs/mod.md b/thaw/src/time_picker/docs/mod.md index 9c39e034..53287876 100644 --- a/thaw/src/time_picker/docs/mod.md +++ b/thaw/src/time_picker/docs/mod.md @@ -7,10 +7,24 @@ let value = RwSignal::new(Local::now().time()); let option_value = RwSignal::new(Local::now().time()); view! { - + - + +} +``` + +### Disabled + +```rust demo +use chrono::prelude::*; +let value = RwSignal::new(Local::now().time()); + +view! { + + + + } ``` @@ -18,7 +32,7 @@ view! { ```rust demo view! { - + @@ -32,6 +46,7 @@ view! { | --- | --- | --- | --- | | class | `MaybeProp` | `Default::default()` | | | id | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Whether time picker is disabled. | | name | `MaybeProp` | `Default::default()` | A string specifying a name for the input control. This name is submitted along with the control's value when the form data is submitted. | | rules | `Vec` | `vec![]` | The rules to validate Field. | | value | `OptionModel` | `Default::default()` | Set the TimePicker value. | diff --git a/thaw/src/time_picker/mod.rs b/thaw/src/time_picker/mod.rs index 5387a3fb..fab712d3 100644 --- a/thaw/src/time_picker/mod.rs +++ b/thaw/src/time_picker/mod.rs @@ -19,6 +19,9 @@ use thaw_utils::{ pub fn TimePicker( #[prop(optional, into)] class: MaybeProp, #[prop(optional, into)] id: MaybeProp, + /// Whether time picker is disabled. + #[prop(optional, into)] + disabled: Signal, /// A string specifying a name for the input control. /// This name is submitted along with the control's value when the form data is submitted. #[prop(optional, into)] @@ -92,6 +95,9 @@ pub fn TimePicker( }; let open_panel = move || { + if disabled.get() { + return; + } if is_show_panel.get() { return; } @@ -114,6 +120,7 @@ pub fn TimePicker( Date: Wed, 20 Aug 2025 09:37:28 +0800 Subject: [PATCH 7/9] feat: Tag adds disabled prop --- thaw/src/tag/docs/mod.md | 27 ++++++++++--- thaw/src/tag/docs/tag_group/mod.md | 15 +++++++ thaw/src/tag/interaction-tag.css | 7 ++++ thaw/src/tag/interaction_tag.rs | 19 ++++++++- thaw/src/tag/mod.rs | 63 +++++++++++++++++------------- thaw/src/tag/tag.css | 17 ++++++-- thaw/src/tag/tag_group.rs | 5 +++ 7 files changed, 116 insertions(+), 37 deletions(-) diff --git a/thaw/src/tag/docs/mod.md b/thaw/src/tag/docs/mod.md index 04452195..c13dce9a 100644 --- a/thaw/src/tag/docs/mod.md +++ b/thaw/src/tag/docs/mod.md @@ -13,6 +13,21 @@ view! { } ``` +### Disabled + +```rust demo +view! { + + "Disabled" + + + "Interaction Tag" + + + +} +``` + ### Size ```rust demo @@ -58,6 +73,7 @@ view! { | Name | Type | Default | Description | | --- | --- | --- | --- | | class | `MaybeProp` | `Default::default()` | | +| disabled | `Option>` | `None` | Whether the tag is disabled. | | size | `Option>` | `None` | Size of the tag. | | dismissible | `Signal` | `false` | A Tag can be dismissible. | | on_dismiss | `Option>` | `None` | Callback for when a tag is dismissed. | @@ -66,11 +82,12 @@ view! { ### InteractionTag Props -| Name | Type | Default | Description | -| -------- | ------------------------- | -------------------- | ---------------- | -| class | `MaybeProp` | `Default::default()` | | -| size | `Option>` | `None` | Size of the tag. | -| children | `Children` | | | +| Name | Type | Default | Description | +| -------- | ------------------------- | -------------------- | ---------------------------------------- | +| class | `MaybeProp` | `Default::default()` | | +| disabled | `Option>` | `None` | Whether the interaction tag is disabled. | +| size | `Option>` | `None` | Size of the tag. | +| children | `Children` | | | ### InteractionTagPrimary Props diff --git a/thaw/src/tag/docs/tag_group/mod.md b/thaw/src/tag/docs/tag_group/mod.md index f2be81f7..598e414d 100644 --- a/thaw/src/tag/docs/tag_group/mod.md +++ b/thaw/src/tag/docs/tag_group/mod.md @@ -23,6 +23,20 @@ view! { } ``` +### Disabled + +```rust demo +view! { + + "Tag 1" + "Tag 1" + + "Tag 1" + + +} +``` + ### Sizes ```rust demo @@ -51,6 +65,7 @@ view! { | Name | Type | Default | Description | | ----------- | -------------------------------- | -------------------- | ------------------------------------- | | class | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Whether the tag group is disabled. | | size | `Signal` | `TagSize::Medium` | Size of the tag. | | dismissible | `Signal` | `false` | A Tag can be dismissible. | | on_dismiss | `Option>` | `None` | Callback for when a tag is dismissed. | diff --git a/thaw/src/tag/interaction-tag.css b/thaw/src/tag/interaction-tag.css index af9359c3..d0819b01 100644 --- a/thaw/src/tag/interaction-tag.css +++ b/thaw/src/tag/interaction-tag.css @@ -51,6 +51,13 @@ background-color: var(--colorNeutralBackground3Pressed); } +.thaw-interaction-tag--disabled .thaw-interaction-tag-primary { + background-color: var(--colorNeutralBackgroundDisabled); + color: var(--colorNeutralForegroundDisabled); + border-color: var(--colorTransparentStrokeDisabled); + cursor: not-allowed; +} + .thaw-interaction-tag-primary__primary-text { grid-row-end: secondary; grid-row-start: primary; diff --git a/thaw/src/tag/interaction_tag.rs b/thaw/src/tag/interaction_tag.rs index 8603f3f8..bb34797f 100644 --- a/thaw/src/tag/interaction_tag.rs +++ b/thaw/src/tag/interaction_tag.rs @@ -5,6 +5,9 @@ use thaw_utils::{class_list, mount_style}; #[component] pub fn InteractionTag( #[prop(optional, into)] class: MaybeProp, + /// Whether the interaction tag is disabled. + #[prop(optional, into)] + disabled: Option>, /// Size of the tag. #[prop(optional, into)] size: Option>, @@ -12,11 +15,22 @@ pub fn InteractionTag( ) -> impl IntoView { mount_style("interaction-tag", include_str!("./interaction-tag.css")); let tag_group = TagGroupInjection::use_context(); + + let disabled = { + if let Some(disabled) = disabled { + Some(disabled) + } else if let Some(tag_group) = &tag_group { + Some(tag_group.disabled.clone()) + } else { + None + } + }; + let size_class = { if let Some(size) = size { Some(size) - } else if let Some(tag_group) = tag_group { - Some(tag_group.size) + } else if let Some(tag_group) = &tag_group { + Some(tag_group.size.clone()) } else { None } @@ -25,6 +39,7 @@ pub fn InteractionTag( view! {
{children()}
diff --git a/thaw/src/tag/mod.rs b/thaw/src/tag/mod.rs index 54ce4350..0904ef71 100644 --- a/thaw/src/tag/mod.rs +++ b/thaw/src/tag/mod.rs @@ -4,12 +4,16 @@ mod tag_group; pub use interaction_tag::*; pub use tag_group::*; +use crate::DismissRegularIcon; use leptos::{either::Either, ev, prelude::*}; use thaw_utils::{class_list, mount_style, ArcOneCallback}; #[component] pub fn Tag( #[prop(optional, into)] class: MaybeProp, + /// Whether the tag is disabled. + #[prop(optional, into)] + disabled: Option>, /// Size of the tag. #[prop(optional, into)] size: Option>, @@ -25,21 +29,33 @@ pub fn Tag( children: Children, ) -> impl IntoView { mount_style("tag", include_str!("./tag.css")); - let (group_size, group_on_dismiss, group_dismissible) = TagGroupInjection::use_context() - .map( - |TagGroupInjection { - size, - on_dismiss, - dismissible, - }| { - if value.is_none() { - (Some(size), None, None) - } else { - (Some(size), on_dismiss, Some(dismissible)) - } - }, - ) - .unwrap_or_default(); + let (group_disabled, group_size, group_on_dismiss, group_dismissible) = + TagGroupInjection::use_context() + .map( + |TagGroupInjection { + disabled, + size, + on_dismiss, + dismissible, + }| { + if value.is_none() { + (Some(disabled), Some(size), None, None) + } else { + (Some(disabled), Some(size), on_dismiss, Some(dismissible)) + } + }, + ) + .unwrap_or_default(); + + let disabled = { + if let Some(disabled) = disabled { + Some(disabled) + } else if let Some(disabled) = group_disabled { + Some(disabled) + } else { + None + } + }; let size_class = { if let Some(size) = size { @@ -55,6 +71,7 @@ pub fn Tag( @@ -67,6 +84,9 @@ pub fn Tag( let group_on_dismiss = group_on_dismiss.clone(); let value = value.clone(); let on_dismiss = move |event: ev::MouseEvent| { + if disabled.map_or(false, |d| d.get()) { + return; + } if let Some(on_dismiss) = group_on_dismiss.as_ref() { event.prevent_default(); on_dismiss(value.clone().unwrap()); @@ -79,18 +99,7 @@ pub fn Tag( Either::Left( view! { }, ) diff --git a/thaw/src/tag/tag.css b/thaw/src/tag/tag.css index 6247def2..f7dc5c5f 100644 --- a/thaw/src/tag/tag.css +++ b/thaw/src/tag/tag.css @@ -17,6 +17,13 @@ border-radius: var(--borderRadiusMedium); } +.thaw-tag--disabled { + background-color: var(--colorNeutralBackgroundDisabled); + color: var(--colorNeutralForegroundDisabled); + border-color: var(--colorTransparentStrokeDisabled); + cursor: not-allowed; +} + .thaw-tag--small { height: 24px; padding: 0 5px; @@ -41,7 +48,6 @@ font-weight: var(--fontWeightRegular); font-size: var(--fontSizeBase300); font-family: var(--fontFamilyBase); - color: var(--colorNeutralForeground2); } .thaw-tag--small .thaw-tag__primary-text, @@ -62,6 +68,11 @@ cursor: pointer; } +.thaw-tag--disabled .thaw-tag__dismiss { + color: currentColor; + cursor: not-allowed; +} + .thaw-tag--small .thaw-tag__dismiss { padding-left: var(--spacingHorizontalXXS); font-size: 16px; @@ -79,10 +90,10 @@ line-height: 0; } -.thaw-tag__dismiss:hover { +.thaw-tag:not(.thaw-tag--disabled) > .thaw-tag__dismiss:hover { color: var(--colorCompoundBrandForeground1Hover); } -.thaw-tag__dismiss:active { +.thaw-tag:not(.thaw-tag--disabled) > .thaw-tag__dismiss:active { color: var(--colorCompoundBrandForeground1Pressed); } diff --git a/thaw/src/tag/tag_group.rs b/thaw/src/tag/tag_group.rs index 4d63a5d5..00ab0dd7 100644 --- a/thaw/src/tag/tag_group.rs +++ b/thaw/src/tag/tag_group.rs @@ -5,6 +5,9 @@ use thaw_utils::{class_list, mount_style, ArcOneCallback}; #[component] pub fn TagGroup( #[prop(optional, into)] class: MaybeProp, + /// Whether the tag group is disabled. + #[prop(optional, into)] + disabled: Signal, /// Size of the tag. #[prop(optional, into)] size: Signal, @@ -21,6 +24,7 @@ pub fn TagGroup( view! {
, pub size: Signal, pub on_dismiss: Option>, pub dismissible: Signal, From 13a78b270ea5323dd74c4e3f04986b217c0bebf3 Mon Sep 17 00:00:00 2001 From: lizidev Date: Wed, 20 Aug 2025 09:37:39 +0800 Subject: [PATCH 8/9] feat: TagPicker adds disabled prop --- thaw/src/tag_picker/docs/mod.md | 54 ++++++++++++++++--- thaw/src/tag_picker/tag_picker/mod.rs | 8 +++ thaw/src/tag_picker/tag_picker/tag-picker.css | 22 +++++++- thaw/src/tag_picker/tag_picker/types.rs | 1 + thaw/src/tag_picker/tag_picker_group.rs | 9 +++- thaw/src/tag_picker/tag_picker_input.rs | 6 ++- 6 files changed, 90 insertions(+), 10 deletions(-) diff --git a/thaw/src/tag_picker/docs/mod.md b/thaw/src/tag_picker/docs/mod.md index 3e2ba386..5cb1bea6 100644 --- a/thaw/src/tag_picker/docs/mod.md +++ b/thaw/src/tag_picker/docs/mod.md @@ -37,6 +37,45 @@ view! { } ``` +### Disabled + +```rust demo +let selected_options = RwSignal::new(vec!["Cat".to_string()]); +let options = vec!["Cat", "Dog"]; + +view! { + + + + {move || { + selected_options.get().into_iter().map(|option| view!{ + + {option} + + }).collect_view() + }} + + + + { + move || { + selected_options.with(|selected_options| { + options.iter().filter_map(|option| { + if selected_options.iter().any(|o| o == option) { + return None + } else { + Some(view! { + + }) + } + }).collect_view() + }) + } + } + +} +``` + ### Size ```rust demo @@ -210,13 +249,14 @@ view! { ### TagPicker Props -| Name | Type | Default | Description | -| ------------------ | ----------------------- | ----------------------- | --------------------------------- | -| class | `MaybeProp` | `Default::default()` | | -| selected_option | `Model>` | `Default::default()` | An array of selected option keys. | -| size | `Signal` | `TagPickerSize::Medium` | The size of the TagPicker. | -| tag_picker_control | slot `TagPickerControl` | | | -| children | `Children` | | | +| Name | Type | Default | Description | +| ------------------ | ----------------------- | ----------------------- | ----------------------------------- | +| class | `MaybeProp` | `Default::default()` | | +| disabled | `Signal` | `false` | Whether the tag picker is disabled. | +| selected_option | `Model>` | `Default::default()` | An array of selected option keys. | +| size | `Signal` | `TagPickerSize::Medium` | The size of the TagPicker. | +| tag_picker_control | slot `TagPickerControl` | | | +| children | `Children` | | | ### TagPickerGroup Props diff --git a/thaw/src/tag_picker/tag_picker/mod.rs b/thaw/src/tag_picker/tag_picker/mod.rs index 22e9cf5d..3aad93fb 100644 --- a/thaw/src/tag_picker/tag_picker/mod.rs +++ b/thaw/src/tag_picker/tag_picker/mod.rs @@ -15,6 +15,9 @@ use thaw_utils::{call_on_click_outside_with_list, class_list, mount_style, Model #[component] pub fn TagPicker( #[prop(optional, into)] class: MaybeProp, + /// Whether the tag picker is disabled. + #[prop(optional, into)] + disabled: Signal, /// An array of selected option keys. #[prop(optional, into)] selected_options: Model>, @@ -40,6 +43,7 @@ pub fn TagPicker( let tag_picker_control_injection = TagPickerControlInjection(active_descendant_controller.clone()); let tag_picker_injection = TagPickerInjection { + disabled, size, selected_options, input_ref, @@ -48,6 +52,9 @@ pub fn TagPicker( listbox_hidden_callback, }; let on_click = move |e: ev::MouseEvent| { + if disabled.get() { + return; + } if e.default_prevented() { if is_show_listbox.get() { is_show_listbox.set(false); @@ -105,6 +112,7 @@ pub fn TagPicker(
, pub size: Signal, pub input_ref: NodeRef, pub(super) selected_options: Model>, diff --git a/thaw/src/tag_picker/tag_picker_group.rs b/thaw/src/tag_picker/tag_picker_group.rs index 1ae6e164..07f08d47 100644 --- a/thaw/src/tag_picker/tag_picker_group.rs +++ b/thaw/src/tag_picker/tag_picker_group.rs @@ -24,7 +24,14 @@ pub fn TagPickerGroup( }; view! { - + {children()} } diff --git a/thaw/src/tag_picker/tag_picker_input.rs b/thaw/src/tag_picker/tag_picker_input.rs index f205a018..66f1072d 100644 --- a/thaw/src/tag_picker/tag_picker_input.rs +++ b/thaw/src/tag_picker/tag_picker_input.rs @@ -5,7 +5,10 @@ use thaw_utils::class_list; #[component] pub fn TagPickerInput(#[prop(optional, into)] class: MaybeProp) -> impl IntoView { let TagPickerInjection { - input_ref, options, .. + disabled, + input_ref, + options, + .. } = TagPickerInjection::expect_context(); let TagPickerControlInjection(active_descendant_controller) = TagPickerControlInjection::expect_context(); @@ -40,6 +43,7 @@ pub fn TagPickerInput(#[prop(optional, into)] class: MaybeProp) -> impl view! { Date: Wed, 20 Aug 2025 09:39:55 +0800 Subject: [PATCH 9/9] style: cargo fmt & leptosfmt --- thaw/src/accordion/accordion_item.rs | 4 +--- thaw/src/date_picker/panel/date_panel.rs | 14 ++++++++------ thaw/src/date_picker/panel/month_panel.rs | 4 +++- thaw/src/icon/icons/mod.rs | 4 ++-- thaw/src/popover/mod.rs | 6 +++++- thaw/src/radio/radio_group.rs | 9 +++++++-- thaw/src/tooltip/tooltip.rs | 6 +++++- 7 files changed, 31 insertions(+), 16 deletions(-) diff --git a/thaw/src/accordion/accordion_item.rs b/thaw/src/accordion/accordion_item.rs index eced4119..5615ddad 100644 --- a/thaw/src/accordion/accordion_item.rs +++ b/thaw/src/accordion/accordion_item.rs @@ -72,9 +72,7 @@ pub fn AccordionItem(
-
- {children()} -
+
{children()}
} diff --git a/thaw/src/date_picker/panel/date_panel.rs b/thaw/src/date_picker/panel/date_panel.rs index 3a837485..b68c549a 100644 --- a/thaw/src/date_picker/panel/date_panel.rs +++ b/thaw/src/date_picker/panel/date_panel.rs @@ -147,17 +147,19 @@ pub fn DatePanel( />
- {move|| { - let first_weekday_number = locale.get().first_weekday().num_days_from_sunday() as u8; + {move || { + let first_weekday_number = locale + .get() + .first_weekday() + .num_days_from_sunday() as u8; let last_weekday_number = first_weekday_number + 6; (first_weekday_number..=last_weekday_number) .into_iter() .map(|n| { - view! { {locale.get().ab_day(n%7)}} + view! { {locale.get().ab_day(n % 7)} } }) .collect_view() - } - } + }}
{move || { @@ -181,7 +183,7 @@ pub fn DatePanel(
diff --git a/thaw/src/date_picker/panel/month_panel.rs b/thaw/src/date_picker/panel/month_panel.rs index 3e8b513f..effc2745 100644 --- a/thaw/src/date_picker/panel/month_panel.rs +++ b/thaw/src/date_picker/panel/month_panel.rs @@ -93,7 +93,9 @@ fn MonthPanelItem(date_panel_show_date: RwSignal, month: Month) -> im class="thaw-date-picker-month-panel__item" class=("thaw-date-picker-month-panel__item--selected", move || is_selected.get()) > -
{locale.get().ab_month(month.number_from_month() as u8)}
+
+ {locale.get().ab_month(month.number_from_month() as u8)} +
} } diff --git a/thaw/src/icon/icons/mod.rs b/thaw/src/icon/icons/mod.rs index 40439c23..ea0c2712 100644 --- a/thaw/src/icon/icons/mod.rs +++ b/thaw/src/icon/icons/mod.rs @@ -32,8 +32,8 @@ pub fn ChevronRight12RegularIcon() -> impl IntoView { > - + fill="currentColor" + > } } diff --git a/thaw/src/popover/mod.rs b/thaw/src/popover/mod.rs index 77ef719e..c8e6cc1b 100644 --- a/thaw/src/popover/mod.rs +++ b/thaw/src/popover/mod.rs @@ -167,7 +167,11 @@ where on:mouseleave=on_mouse_leave > {children()} -
+
diff --git a/thaw/src/radio/radio_group.rs b/thaw/src/radio/radio_group.rs index 54f20f28..c6f6138f 100644 --- a/thaw/src/radio/radio_group.rs +++ b/thaw/src/radio/radio_group.rs @@ -11,7 +11,8 @@ pub fn RadioGroup( #[prop(optional, into)] disabled: Signal, /// The rules to validate Field. - #[prop(optional, into)] rules: Vec, + #[prop(optional, into)] + rules: Vec, /// The selected Radio item in this group. #[prop(optional, into)] value: OptionModel, @@ -36,7 +37,11 @@ pub fn RadioGroup( }); view! { - +
{children()}
diff --git a/thaw/src/tooltip/tooltip.rs b/thaw/src/tooltip/tooltip.rs index 6e502854..7ec3f8b6 100644 --- a/thaw/src/tooltip/tooltip.rs +++ b/thaw/src/tooltip/tooltip.rs @@ -94,7 +94,11 @@ where on:mouseleave=on_mouse_leave > {move || { content.as_ref().map(|c| c.get()).unwrap_or_default() }} -
+