Skip to content

Commit 9789d42

Browse files
authored
feat: Button icon property supports the signal (#132)
1 parent c1a9f84 commit 9789d42

File tree

4 files changed

+144
-22
lines changed

4 files changed

+144
-22
lines changed

demo_markdown/docs/button/mod.md

+45-15
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,51 @@ view! {
2727
### Icon
2828

2929
```rust demo
30+
let icon = create_rw_signal(Some(icondata::AiCloseOutlined));
31+
32+
let on_click = move |_| {
33+
icon.update(|icon| {
34+
*icon = match icon {
35+
Some(data) => {
36+
if *data == icondata::AiCloseOutlined {
37+
icondata::AiCheckOutlined
38+
} else {
39+
icondata::AiCloseOutlined
40+
}
41+
}
42+
None => icondata::AiCloseOutlined
43+
}.into();
44+
});
45+
};
46+
3047
view! {
31-
<Space>
32-
<Button color=ButtonColor::Error icon=icondata::AiCloseOutlined>
33-
"Error Color Icon"
34-
</Button>
35-
<Button
36-
color=ButtonColor::Error
37-
icon=icondata::AiCloseOutlined
38-
round=true
39-
/>
40-
<Button
41-
color=ButtonColor::Error
42-
icon=icondata::AiCloseOutlined
43-
circle=true
44-
/>
48+
<Space vertical=true>
49+
<Space>
50+
<Button icon on_click>
51+
"Change icon"
52+
</Button>
53+
<Button icon on_click=move |_| icon.set(None)>
54+
"Clear icon"
55+
</Button>
56+
</Space>
57+
<Space>
58+
<Button color=ButtonColor::Error icon=icondata::AiCloseOutlined>
59+
"Error Color Icon"
60+
</Button>
61+
<Button color=ButtonColor::Error icon=icondata::AiCloseOutlined>
62+
"Error Color Icon"
63+
</Button>
64+
<Button
65+
color=ButtonColor::Error
66+
icon=icondata::AiCloseOutlined
67+
round=true
68+
/>
69+
<Button
70+
color=ButtonColor::Error
71+
icon=icondata::AiCloseOutlined
72+
circle=true
73+
/>
74+
</Space>
4575
</Space>
4676
}
4777
```
@@ -135,7 +165,7 @@ view! {
135165
| color | `MaybeSignal<ButtonColor>` | `ButtonColor::Primary` | Button's color. |
136166
| round | `MaybeSignal<bool>` | `false` | Whether the button shows rounded corners. |
137167
| circle | `MaybeSignal<bool>` | `false` | Whether the button is round. |
138-
| icon | `Option<Icon>` | `None` | The icon of the button. |
168+
| icon | `OptionalMaybeSignal<icondata_core::Icon>` | `None` | The icon of the button. |
139169
| loading | `MaybeSignal<bool>` | `false` | Whether the button shows the loading status. |
140170
| disabled | `MaybeSignal<bool>` | `false` | Whether the button is disabled. |
141171
| size | `MaybeSignal<ButtonSize>` | `ButtonSize::Medium` | Button size. |

thaw/src/button/mod.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
components::{OptionComp, Wave, WaveRef},
66
icon::Icon,
77
theme::*,
8-
utils::{class_list::class_list, mount_style, ComponentRef, OptionalProp},
8+
utils::{class_list::class_list, mount_style, ComponentRef, OptionalMaybeSignal, OptionalProp},
99
};
1010
pub use button_group::ButtonGroup;
1111
use leptos::*;
@@ -104,7 +104,7 @@ pub fn Button(
104104
#[prop(optional, into)] size: MaybeSignal<ButtonSize>,
105105
#[prop(optional, into)] round: MaybeSignal<bool>,
106106
#[prop(optional, into)] circle: MaybeSignal<bool>,
107-
#[prop(optional, into)] icon: Option<icondata_core::Icon>,
107+
#[prop(optional, into)] icon: OptionalMaybeSignal<icondata_core::Icon>,
108108
#[prop(optional, into)] loading: MaybeSignal<bool>,
109109
#[prop(optional, into)] disabled: MaybeSignal<bool>,
110110
#[prop(optional, into)] on_click: Option<Callback<ev::MouseEvent>>,
@@ -248,12 +248,17 @@ pub fn Button(
248248
"animation: thawLoadingCircle 1s infinite linear;{icon_style}",
249249
)
250250
/>
251-
}
252-
.into()
253-
} else if let Some(icon) = icon {
254-
view! { <Icon icon=icon style=icon_style/> }.into()
251+
}.into_view()
252+
255253
} else {
256-
None
254+
(move || {
255+
let icon = icon.get();
256+
view! {
257+
<OptionComp value=icon let:icon>
258+
<Icon icon=icon style=icon_style/>
259+
</OptionComp>
260+
}
261+
}).into_view()
257262
}
258263
}}
259264

thaw/src/utils/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod component_ref;
44
mod event_listener;
55
mod model;
66
mod mount_style;
7+
mod optional_maybe_signal;
78
mod optional_prop;
89
mod signal;
910
mod stored_maybe_signal;
@@ -16,6 +17,7 @@ pub use component_ref::{create_component_ref, ComponentRef};
1617
pub(crate) use event_listener::*;
1718
pub(crate) use model::Model;
1819
pub(crate) use mount_style::mount_style;
20+
pub(crate) use optional_maybe_signal::OptionalMaybeSignal;
1921
pub(crate) use optional_prop::OptionalProp;
2022
pub use signal::SignalWatch;
2123
pub(crate) use stored_maybe_signal::*;
+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use leptos::*;
2+
use std::ops::Deref;
3+
4+
pub struct OptionalMaybeSignal<T: 'static>(MaybeSignal<Option<T>>);
5+
6+
impl<T> Default for OptionalMaybeSignal<T> {
7+
fn default() -> Self {
8+
Self(MaybeSignal::Static(None))
9+
}
10+
}
11+
12+
impl<T: Copy> Copy for OptionalMaybeSignal<T> {}
13+
14+
impl<T: Clone> Clone for OptionalMaybeSignal<T> {
15+
fn clone(&self) -> Self {
16+
Self(self.0.clone())
17+
}
18+
}
19+
20+
impl<T> Deref for OptionalMaybeSignal<T> {
21+
type Target = MaybeSignal<Option<T>>;
22+
23+
fn deref(&self) -> &Self::Target {
24+
&self.0
25+
}
26+
}
27+
28+
impl<T> From<T> for OptionalMaybeSignal<T> {
29+
fn from(value: T) -> Self {
30+
Self(MaybeSignal::Static(Some(value)))
31+
}
32+
}
33+
34+
impl<T> From<Option<T>> for OptionalMaybeSignal<T> {
35+
fn from(value: Option<T>) -> Self {
36+
Self(MaybeSignal::Static(value))
37+
}
38+
}
39+
40+
impl<T> From<ReadSignal<Option<T>>> for OptionalMaybeSignal<T> {
41+
fn from(value: ReadSignal<Option<T>>) -> Self {
42+
Self(MaybeSignal::Dynamic(value.into()))
43+
}
44+
}
45+
46+
impl<T> From<RwSignal<Option<T>>> for OptionalMaybeSignal<T> {
47+
fn from(value: RwSignal<Option<T>>) -> Self {
48+
Self(MaybeSignal::Dynamic(value.into()))
49+
}
50+
}
51+
52+
impl<T> From<Memo<Option<T>>> for OptionalMaybeSignal<T> {
53+
fn from(value: Memo<Option<T>>) -> Self {
54+
Self(MaybeSignal::Dynamic(value.into()))
55+
}
56+
}
57+
58+
impl<T> From<Signal<Option<T>>> for OptionalMaybeSignal<T> {
59+
fn from(value: Signal<Option<T>>) -> Self {
60+
Self(MaybeSignal::Dynamic(value))
61+
}
62+
}
63+
64+
impl<T> From<MaybeSignal<Option<T>>> for OptionalMaybeSignal<T> {
65+
fn from(value: MaybeSignal<Option<T>>) -> Self {
66+
Self(value)
67+
}
68+
}
69+
70+
#[cfg(test)]
71+
mod test {
72+
use super::OptionalMaybeSignal;
73+
use leptos::{create_runtime, MaybeSignal};
74+
75+
#[test]
76+
fn into() {
77+
let runtime = create_runtime();
78+
79+
let _: MaybeSignal<i32> = 12.into();
80+
let _: OptionalMaybeSignal<i32> = Some(12).into();
81+
let _: OptionalMaybeSignal<i32> = MaybeSignal::Static(Some(12)).into();
82+
83+
runtime.dispose();
84+
}
85+
}

0 commit comments

Comments
 (0)