2023-03-31 13:02:44 +08:00
|
|
|
mod theme;
|
2023-10-07 21:41:03 +08:00
|
|
|
|
2023-11-02 10:16:31 +08:00
|
|
|
use crate::{
|
2023-11-13 16:17:41 +08:00
|
|
|
components::{OptionComp, Wave, WaveRef},
|
2023-11-02 10:16:31 +08:00
|
|
|
icon::*,
|
|
|
|
theme::*,
|
|
|
|
utils::{mount_style::mount_style, ComponentRef},
|
|
|
|
};
|
2023-03-28 12:37:24 +08:00
|
|
|
use leptos::*;
|
2023-03-31 13:02:44 +08:00
|
|
|
pub use theme::ButtonTheme;
|
|
|
|
|
2023-04-12 17:48:11 +08:00
|
|
|
#[derive(Default, PartialEq, Clone, Copy)]
|
2023-10-08 14:01:24 +08:00
|
|
|
pub enum ButtonVariant {
|
2023-03-31 13:02:44 +08:00
|
|
|
#[default]
|
2023-10-16 21:15:43 +08:00
|
|
|
Primary,
|
|
|
|
Solid,
|
|
|
|
Text,
|
|
|
|
Link,
|
2023-03-31 13:02:44 +08:00
|
|
|
}
|
|
|
|
|
2023-04-04 15:55:14 +08:00
|
|
|
#[derive(Default, Clone)]
|
2023-03-31 13:02:44 +08:00
|
|
|
pub enum ButtonColor {
|
|
|
|
#[default]
|
2023-10-16 21:15:43 +08:00
|
|
|
Primary,
|
|
|
|
Success,
|
|
|
|
Warning,
|
|
|
|
Error,
|
2023-03-31 13:02:44 +08:00
|
|
|
}
|
2023-03-28 12:37:24 +08:00
|
|
|
|
2023-04-04 15:55:14 +08:00
|
|
|
impl ButtonColor {
|
|
|
|
pub fn theme_color(&self, theme: &Theme) -> String {
|
|
|
|
match self {
|
2023-10-16 21:15:43 +08:00
|
|
|
ButtonColor::Primary => theme.common.color_primary.clone(),
|
|
|
|
ButtonColor::Success => theme.common.color_success.clone(),
|
|
|
|
ButtonColor::Warning => theme.common.color_warning.clone(),
|
|
|
|
ButtonColor::Error => theme.common.color_error.clone(),
|
2023-04-04 15:55:14 +08:00
|
|
|
}
|
|
|
|
}
|
2023-09-17 23:10:33 +08:00
|
|
|
pub fn theme_color_hover(&self, theme: &Theme) -> String {
|
|
|
|
match self {
|
2023-10-16 21:15:43 +08:00
|
|
|
ButtonColor::Primary => theme.common.color_primary_hover.clone(),
|
|
|
|
ButtonColor::Success => theme.common.color_success_hover.clone(),
|
|
|
|
ButtonColor::Warning => theme.common.color_warning_hover.clone(),
|
|
|
|
ButtonColor::Error => theme.common.color_error_hover.clone(),
|
2023-09-17 23:10:33 +08:00
|
|
|
}
|
|
|
|
}
|
2023-10-04 22:25:12 +08:00
|
|
|
|
|
|
|
pub fn theme_color_active(&self, theme: &Theme) -> String {
|
|
|
|
match self {
|
2023-10-16 21:15:43 +08:00
|
|
|
ButtonColor::Primary => theme.common.color_primary_active.clone(),
|
|
|
|
ButtonColor::Success => theme.common.color_success_active.clone(),
|
|
|
|
ButtonColor::Warning => theme.common.color_warning_active.clone(),
|
|
|
|
ButtonColor::Error => theme.common.color_error_active.clone(),
|
2023-10-04 22:25:12 +08:00
|
|
|
}
|
|
|
|
}
|
2023-04-04 15:55:14 +08:00
|
|
|
}
|
|
|
|
|
2023-03-28 12:37:24 +08:00
|
|
|
#[component]
|
2023-03-31 13:02:44 +08:00
|
|
|
pub fn Button(
|
2023-06-07 23:42:04 +08:00
|
|
|
#[prop(optional, into)] style: MaybeSignal<String>,
|
2023-10-08 14:01:24 +08:00
|
|
|
#[prop(optional, into)] variant: MaybeSignal<ButtonVariant>,
|
2023-03-31 13:02:44 +08:00
|
|
|
#[prop(optional, into)] color: MaybeSignal<ButtonColor>,
|
2023-05-08 23:53:54 +08:00
|
|
|
#[prop(optional, into)] round: MaybeSignal<bool>,
|
2023-06-09 22:24:39 +08:00
|
|
|
#[prop(optional, into)] icon: Option<Icon>,
|
2023-10-05 11:06:43 +08:00
|
|
|
#[prop(optional, into)] loading: MaybeSignal<bool>,
|
2023-10-05 11:52:18 +08:00
|
|
|
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
|
|
|
#[prop(optional, into)] on_click: Option<Callback<ev::MouseEvent>>,
|
2023-06-09 22:24:39 +08:00
|
|
|
#[prop(optional)] children: Option<ChildrenFn>,
|
2023-03-31 13:02:44 +08:00
|
|
|
) -> impl IntoView {
|
2023-08-29 09:11:22 +08:00
|
|
|
let theme = use_theme(Theme::light);
|
|
|
|
let css_vars = create_memo(move |_| {
|
2023-04-12 17:48:11 +08:00
|
|
|
let mut css_vars = String::new();
|
2023-10-26 18:03:24 +08:00
|
|
|
theme.with(|theme| {
|
2023-10-26 23:24:16 +08:00
|
|
|
let bg_color = color.get().theme_color(theme);
|
2023-10-26 18:03:24 +08:00
|
|
|
if variant.get() == ButtonVariant::Primary {
|
2023-10-26 23:24:16 +08:00
|
|
|
let bg_color_hover = color.get().theme_color_hover(theme);
|
|
|
|
let bg_color_active = color.get().theme_color_active(theme);
|
2023-11-05 16:03:58 +08:00
|
|
|
css_vars.push_str(&format!("--thaw-background-color: {bg_color};"));
|
|
|
|
css_vars.push_str(&format!("--thaw-background-color-hover: {bg_color_hover};"));
|
2023-11-02 22:01:48 +08:00
|
|
|
css_vars.push_str(&format!(
|
2023-11-05 16:03:58 +08:00
|
|
|
"--thaw-background-color-active: {bg_color_active};"
|
2023-11-02 22:01:48 +08:00
|
|
|
));
|
2023-11-05 16:03:58 +08:00
|
|
|
css_vars.push_str("--thaw-font-color: #fff;");
|
|
|
|
css_vars.push_str(&format!("--thaw-border-color: {bg_color};"));
|
|
|
|
css_vars.push_str(&format!("--thaw-border-color-hover: {bg_color};"));
|
|
|
|
css_vars.push_str(&format!("--thaw-ripple-color: {bg_color};"));
|
2023-10-26 18:03:24 +08:00
|
|
|
} else if variant.get() == ButtonVariant::Text {
|
2023-11-05 16:03:58 +08:00
|
|
|
css_vars.push_str(&format!("--thaw-font-color-hover: {bg_color};"));
|
2023-10-26 18:03:24 +08:00
|
|
|
css_vars.push_str(&format!(
|
2023-11-05 16:03:58 +08:00
|
|
|
"--thaw-background-color-hover: {};",
|
2023-10-26 18:03:24 +08:00
|
|
|
theme.button.color_text_hover
|
|
|
|
));
|
|
|
|
css_vars.push_str(&format!(
|
2023-11-05 16:03:58 +08:00
|
|
|
"--thaw-background-color-active: {};",
|
2023-10-26 18:03:24 +08:00
|
|
|
theme.button.color_text_active
|
|
|
|
));
|
2023-11-09 16:46:14 +08:00
|
|
|
css_vars.push_str("--thaw-ripple-color: #0000;");
|
2023-10-26 18:03:24 +08:00
|
|
|
} else {
|
2023-11-05 16:03:58 +08:00
|
|
|
css_vars.push_str(&format!("--thaw-font-color-hover: {bg_color};"));
|
|
|
|
css_vars.push_str("--thaw-border-color: #555a;");
|
|
|
|
css_vars.push_str("--thaw-border-color-hover: #555;");
|
2023-11-09 16:46:14 +08:00
|
|
|
css_vars.push_str("--thaw-ripple-color: #0000;");
|
2023-10-26 18:03:24 +08:00
|
|
|
}
|
|
|
|
});
|
2023-04-12 12:47:31 +08:00
|
|
|
|
2023-04-12 17:48:11 +08:00
|
|
|
css_vars
|
|
|
|
});
|
2023-10-07 21:41:03 +08:00
|
|
|
mount_style("button", include_str!("./button.css"));
|
2023-04-04 15:55:14 +08:00
|
|
|
|
2023-05-15 12:52:03 +08:00
|
|
|
let icon_style = if children.is_some() {
|
2023-05-08 23:53:54 +08:00
|
|
|
"margin-right: 6px"
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
};
|
|
|
|
|
2023-10-05 11:52:18 +08:00
|
|
|
let disabled = create_memo(move |_| {
|
|
|
|
if loading.get() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
disabled.get()
|
|
|
|
});
|
|
|
|
|
2023-11-02 10:16:31 +08:00
|
|
|
let wave_ref = ComponentRef::<WaveRef>::default();
|
|
|
|
|
2023-10-05 11:52:18 +08:00
|
|
|
let on_click = move |event| {
|
|
|
|
if disabled.get() {
|
|
|
|
return;
|
|
|
|
}
|
2023-11-02 10:16:31 +08:00
|
|
|
if let Some(wave_ref) = wave_ref.get_untracked() {
|
|
|
|
wave_ref.play();
|
|
|
|
}
|
2023-10-05 11:52:18 +08:00
|
|
|
let Some(callback) = on_click.as_ref() else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
callback.call(event);
|
|
|
|
};
|
|
|
|
|
2023-10-07 21:41:03 +08:00
|
|
|
view! {
|
2023-04-12 12:47:31 +08:00
|
|
|
<button
|
2023-11-05 16:03:58 +08:00
|
|
|
class:thaw-button=true
|
|
|
|
class=("thaw-button--text", move || variant.get() == ButtonVariant::Text)
|
|
|
|
class=("thaw-button--link", move || variant.get() == ButtonVariant::Link)
|
|
|
|
class=("thaw-button--round", move || round.get())
|
|
|
|
class=("thaw-button--disabled", move || disabled.get())
|
2023-06-07 23:42:04 +08:00
|
|
|
style=move || format!("{}{}", css_vars.get(), style.get())
|
2023-10-05 11:52:18 +08:00
|
|
|
on:click=on_click
|
2023-10-08 09:28:13 +08:00
|
|
|
>
|
2023-11-02 10:16:31 +08:00
|
|
|
<Wave comp_ref=wave_ref/>
|
2023-10-08 09:28:13 +08:00
|
|
|
{move || {
|
|
|
|
if loading.get() {
|
|
|
|
view! {
|
|
|
|
<Icon
|
|
|
|
icon=Icon::from(AiIcon::AiLoadingOutlined)
|
|
|
|
style=format!(
|
2023-11-05 16:03:58 +08:00
|
|
|
"animation: thawLoadingCircle 1s infinite linear;{icon_style}",
|
2023-10-08 09:28:13 +08:00
|
|
|
)
|
|
|
|
/>
|
2023-10-05 11:06:43 +08:00
|
|
|
}
|
2023-10-08 09:28:13 +08:00
|
|
|
.into()
|
|
|
|
} else if let Some(icon) = icon {
|
|
|
|
view! { <Icon icon=icon style=icon_style/> }.into()
|
|
|
|
} else {
|
|
|
|
None
|
2023-10-05 11:06:43 +08:00
|
|
|
}
|
2023-10-08 09:28:13 +08:00
|
|
|
}}
|
|
|
|
|
|
|
|
<OptionComp value=children let:children>
|
|
|
|
{children()}
|
|
|
|
</OptionComp>
|
2023-03-28 12:37:24 +08:00
|
|
|
</button>
|
|
|
|
}
|
|
|
|
}
|