refactor: Progress

This commit is contained in:
luoxiao 2024-06-28 10:48:40 +08:00
parent de58ed680b
commit be74dc584e
14 changed files with 133 additions and 233 deletions

View file

@ -73,7 +73,7 @@ fn TheRouter(is_routing: RwSignal<bool>) -> impl IntoView {
<Route path="/message-bar" view=MessageBarMdPage/>
<Route path="/modal" view=ModalMdPage/>
<Route path="/popover" view=PopoverMdPage/>
<Route path="/progress" view=ProgressMdPage/>
<Route path="/progress-bar" view=ProgressBarMdPage/>
<Route path="/radio" view=RadioMdPage/>
<Route path="/scrollbar" view=ScrollbarMdPage/>
// <Route path="/select" view=SelectMdPage/>

View file

@ -244,8 +244,8 @@ pub(crate) fn gen_menu_data() -> Vec<MenuGroupOption> {
label: "Popover".into(),
},
MenuItemOption {
value: "/components/progress".into(),
label: "Progress".into(),
value: "/components/progress-bar".into(),
label: "ProgressBar".into(),
},
MenuItemOption {
value: "/components/radio".into(),

View file

@ -1,19 +1,17 @@
# Progress
# ProgressBar
```rust demo
let percentage = create_rw_signal(0.0f32);
let value = RwSignal::new(0.0);
view! {
<Space vertical=true>
<Progress percentage show_indicator=false/>
<Progress percentage/>
<Progress percentage indicator_placement=ProgressIndicatorPlacement::Inside/>
<Progress percentage color=ProgressColor::Success/>
<Progress percentage color=ProgressColor::Warning/>
<Progress percentage color=ProgressColor::Error/>
<ProgressBar value/>
<ProgressBar value color=ProgressBarColor::Success/>
<ProgressBar value color=ProgressBarColor::Warning/>
<ProgressBar value color=ProgressBarColor::Error/>
<Space>
<Button on_click=move |_| percentage.update(|v| *v -= 10.0)>"-10%"</Button>
<Button on_click=move |_| percentage.update(|v| *v += 10.0)>"+10%"</Button>
<Button on_click=move |_| value.update(|v| *v -= 0.1)>"-10%"</Button>
<Button on_click=move |_| value.update(|v| *v += 0.1)>"+10%"</Button>
</Space>
</Space>
}
@ -22,18 +20,18 @@ view! {
### Circle
```rust demo
let percentage = create_rw_signal(0.0f32);
let value = RwSignal::new(0.0);
view! {
<Space>
<ProgressCircle percentage/>
<ProgressCircle percentage color=ProgressColor::Success/>
<ProgressCircle percentage color=ProgressColor::Warning/>
<ProgressCircle percentage color=ProgressColor::Error/>
<ProgressCircle value/>
<ProgressCircle value color=ProgressCircleColor::Success/>
<ProgressCircle value color=ProgressCircleColor::Warning/>
<ProgressCircle value color=ProgressCircleColor::Error/>
</Space>
<Space>
<Button on_click=move |_| percentage.update(|v| *v -= 10.0)>"-10%"</Button>
<Button on_click=move |_| percentage.update(|v| *v += 10.0)>"+10%"</Button>
<Button on_click=move |_| value.update(|v| *v -= 10.0)>"-10%"</Button>
<Button on_click=move |_| value.update(|v| *v += 10.0)>"+10%"</Button>
</Space>
}
```

View file

@ -56,7 +56,7 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt
"MessageBarMdPage" => "../docs/message_bar/mod.md",
"ModalMdPage" => "../docs/modal/mod.md",
"PopoverMdPage" => "../docs/popover/mod.md",
"ProgressMdPage" => "../docs/progress/mod.md",
"ProgressBarMdPage" => "../docs/progress_bar/mod.md",
"RadioMdPage" => "../docs/radio/mod.md",
"ScrollbarMdPage" => "../docs/scrollbar/mod.md",
// "SelectMdPage" => "../docs/select/mod.md",

View file

@ -27,7 +27,7 @@ mod message_bar;
mod modal;
mod nav;
mod popover;
mod progress;
mod progress_bar;
mod radio;
mod scrollbar;
mod skeleton;
@ -74,7 +74,7 @@ pub use message_bar::*;
pub use modal::*;
pub use nav::*;
pub use popover::*;
pub use progress::*;
pub use progress_bar::*;
pub use radio::*;
pub use scrollbar::*;
pub use skeleton::*;

View file

@ -1,123 +0,0 @@
mod progress_circle;
mod theme;
pub use progress_circle::ProgressCircle;
pub use theme::ProgressTheme;
use crate::{use_theme, Theme};
use leptos::*;
use thaw_utils::mount_style;
#[derive(Default, Clone, PartialEq)]
pub enum ProgressIndicatorPlacement {
#[default]
Outside,
Inside,
}
impl Copy for ProgressIndicatorPlacement {}
impl ProgressIndicatorPlacement {
pub fn as_str(&self) -> &'static str {
match self {
ProgressIndicatorPlacement::Outside => "outside",
ProgressIndicatorPlacement::Inside => "inside",
}
}
}
#[derive(Default, Clone)]
pub enum ProgressColor {
#[default]
Primary,
Success,
Warning,
Error,
}
impl ProgressColor {
fn theme_background_color(&self, theme: &Theme) -> String {
match self {
Self::Primary => theme.common.color_primary.clone(),
Self::Success => theme.common.color_success.clone(),
Self::Warning => theme.common.color_warning.clone(),
Self::Error => theme.common.color_error.clone(),
}
}
}
#[component]
pub fn Progress(
#[prop(into, optional)] percentage: MaybeSignal<f32>,
#[prop(into, optional)] color: MaybeSignal<ProgressColor>,
#[prop(into, default = MaybeSignal::Static(true))] show_indicator: MaybeSignal<bool>,
#[prop(into, optional)] indicator_placement: MaybeSignal<ProgressIndicatorPlacement>,
) -> impl IntoView {
mount_style("progress", include_str!("./progress.css"));
let theme = use_theme(Theme::light);
let css_vars = create_memo(move |_| {
let mut css_vars = String::new();
theme.with(|theme| {
css_vars.push_str(&format!(
"--thaw-background-color: {};",
theme.progress.background_color
));
css_vars.push_str(&format!(
"--thaw-inner-background-color: {};",
color.get().theme_background_color(theme)
));
});
css_vars
});
let style = move || {
let percentage = percentage.get();
let percentage = if percentage < 0.0 {
0.0
} else if percentage > 100.0 {
100.0
} else {
percentage
};
format!("width: {}%;", percentage)
};
let class = move || {
let mut class = String::from("thaw-progress__progress");
class.push_str(&format!(
" thaw-progress__progress--indicator-{}",
indicator_placement.get().as_str()
));
class
};
view! {
<div class="thaw-progress" style=move || css_vars.get()>
<div class=class>
<div class="thaw-progress__progress-inner" style=style>
<Show when=move || {
show_indicator.get()
&& indicator_placement.get() == ProgressIndicatorPlacement::Inside
}>
<div class="thaw-progress__indicator--inside">
{move || { format!("{}%", percentage.get()) }}
</div>
</Show>
</div>
</div>
<Show when=move || {
show_indicator.get()
&& indicator_placement.get() == ProgressIndicatorPlacement::Outside
}>
<div class="thaw-progress__indicator--outside">
{move || { format!("{}%", percentage.get()) }}
</div>
</Show>
</div>
}
}

View file

@ -1,39 +0,0 @@
.thaw-progress {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.thaw-progress__progress {
flex: 1;
position: relative;
height: 8px;
line-height: 8px;
background: var(--thaw-background-color);
border-radius: 4px;
}
.thaw-progress__progress--indicator-inside {
height: 16px;
line-height: 16px;
font-size: 12px;
border-radius: 8px;
}
.thaw-progress__progress-inner {
position: absolute;
background: var(--thaw-inner-background-color);
height: 100%;
border-radius: inherit;
transition: width 0.1s;
}
.thaw-progress__indicator--outside {
padding: 0 8px;
}
.thaw-progress__indicator--inside {
text-align: right;
margin: 0 12px;
}

View file

@ -1,20 +0,0 @@
use crate::theme::ThemeMethod;
#[derive(Clone)]
pub struct ProgressTheme {
pub background_color: String,
}
impl ThemeMethod for ProgressTheme {
fn light() -> Self {
Self {
background_color: "#ebebeb".into(),
}
}
fn dark() -> Self {
Self {
background_color: "#ffffff1f".into(),
}
}
}

View file

@ -0,0 +1,5 @@
mod progress_bar;
mod progress_circle;
pub use progress_bar::*;
pub use progress_circle::*;

View file

@ -0,0 +1,29 @@
.thaw-progress-bar {
display: block;
width: 100%;
height: 2px;
background-color: var(--colorNeutralBackground6);
overflow: hidden;
border-radius: var(--borderRadiusMedium);
}
.thaw-progress-bar__bar {
transition-timing-function: ease;
transition-duration: 0.3s;
transition-property: width;
height: 100%;
background-color: var(--colorCompoundBrandBackground);
border-radius: inherit;
}
.thaw-progress-bar--error .thaw-progress-bar__bar {
background-color: var(--colorPaletteRedBackground3);
}
.thaw-progress-bar--warning .thaw-progress-bar__bar {
background-color: var(--colorPaletteDarkOrangeBackground3);
}
.thaw-progress-bar--success .thaw-progress-bar__bar {
background-color: var(--colorPaletteGreenBackground3);
}

View file

@ -0,0 +1,53 @@
use leptos::*;
use thaw_utils::{class_list, mount_style};
#[component]
pub fn ProgressBar(
#[prop(into, optional)] value: MaybeSignal<f64>,
#[prop(default = 1.0.into(), optional)] max: MaybeSignal<f64>,
#[prop(into, optional)] color: MaybeSignal<ProgressBarColor>,
) -> impl IntoView {
mount_style("progress-bar", include_str!("./progress-bar.css"));
let style = move || {
let max = max.get();
let value = value.get().max(0.0).min(max);
format!("width: {:.02}%;", value / max * 100.0)
};
view! {
<div
class=class_list![
"thaw-progress-bar",
move || format!("thaw-progress-bar--{}", color.get().as_str())
]
role="progressbar"
aria-valuemax=move || max.get()
aria-valuemin="0"
aria-valuenow=move || value.get()
>
<div class="thaw-progress-bar__bar" style=style>
</div>
</div>
}
}
#[derive(Default, Clone)]
pub enum ProgressBarColor {
#[default]
Brand,
Error,
Warning,
Success,
}
impl ProgressBarColor {
pub fn as_str(&self) -> &'static str {
match self {
Self::Brand => "brand",
Self::Error => "error",
Self::Warning => "warning",
Self::Success => "success",
}
}
}

View file

@ -1,18 +1,15 @@
use super::ProgressColor;
use crate::{use_theme, Theme};
use leptos::*;
use thaw_utils::{class_list, mount_style, OptionalProp};
#[component]
pub fn ProgressCircle(
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
#[prop(into, optional)] percentage: MaybeSignal<f32>,
#[prop(into, optional)] color: MaybeSignal<ProgressColor>,
#[prop(into, optional)] value: MaybeSignal<f64>,
#[prop(into, optional)] color: MaybeSignal<ProgressCircleColor>,
#[prop(into, default = "120px".into())] size: MaybeSignal<String>,
#[prop(optional)] children: Option<Children>,
) -> impl IntoView {
mount_style("progress-circle", include_str!("./progress-circle.css"));
let theme = use_theme(Theme::light);
let stroke_width = 7;
let view_box_width = 100;
@ -27,27 +24,23 @@ pub fn ProgressCircle(
let len = std::f64::consts::PI * 2.0 * f64::from(radius);
let rail_stroke_dasharray = format!("{len}px {}px", view_box_width * 8);
let rail_stroke_color =
Memo::new(move |_| theme.with(|theme| theme.progress.background_color.clone()));
let fill_path = rail_path.clone();
let fill_stroke_dasharray = Memo::new(move |_| {
let percentage = percentage.get();
let percentage = if percentage < 0.0 {
0.0
} else if percentage > 100.0 {
100.0
} else {
percentage
};
let percentage = value.get().max(0.0).min(100.0);
format!(
"{}px {}px",
f64::from(percentage / 100.0) * len,
percentage / 100.0 * len,
view_box_width * 8
)
});
let fill_stroke_color =
Memo::new(move |_| theme.with(|theme| color.get().theme_background_color(theme)));
let fill_stroke_color = move || match color.get() {
ProgressCircleColor::Brand => "var(--colorCompoundBrandBackground)",
ProgressCircleColor::Error => "var(--colorPaletteRedBackground3)",
ProgressCircleColor::Warning => "var(--colorPaletteDarkOrangeBackground3)",
ProgressCircleColor::Success => "var(--colorPaletteGreenBackground3)",
};
view! {
<div
@ -55,8 +48,7 @@ pub fn ProgressCircle(
role="progressbar"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow=move || percentage.get()
style=("--thaw-fill-color", move || fill_stroke_color.get())
aria-valuenow=move || value.get()
style=("--thaw-size", move || size.get())
>
@ -67,19 +59,19 @@ pub fn ProgressCircle(
stroke-width=stroke_width
stroke-linecap="round"
fill="none"
style:stroke=move || rail_stroke_color.get()
style:stroke="var(--colorNeutralBackground6)"
style:stroke-dasharray=rail_stroke_dasharray
></path>
</g>
<g>
<path
class=("thaw-progress-circle__fill", true)
class=("thaw-progress-circle__fill--empty", move || percentage.get() <= 0.0)
class=("thaw-progress-circle__fill--empty", move || value.get() <= 0.0)
d=fill_path
stroke-width=stroke_width
stroke-linecap="round"
fill="none"
style:stroke="var(--thaw-fill-color)"
style:stroke=fill_stroke_color
style:stroke-dasharray=move || fill_stroke_dasharray.get()
></path>
</g>
@ -90,7 +82,7 @@ pub fn ProgressCircle(
} else {
view! {
<div class="thaw-progress-circle__content thaw-progress-circle__content--text">
{move || percentage.get()} "%"
{move || value.get()} "%"
</div>
}
}}
@ -98,3 +90,12 @@ pub fn ProgressCircle(
</div>
}
}
#[derive(Default, Clone)]
pub enum ProgressCircleColor {
#[default]
Brand,
Error,
Warning,
Success,
}

View file

@ -2,7 +2,6 @@ mod color;
mod common;
use self::common::CommonTheme;
use crate::ProgressTheme;
pub use color::ColorTheme;
use leptos::*;
@ -16,7 +15,6 @@ pub struct Theme {
pub name: String,
pub common: CommonTheme,
pub color: ColorTheme,
pub progress: ProgressTheme,
}
impl Theme {
@ -25,7 +23,6 @@ impl Theme {
name: "light".into(),
common: CommonTheme::light(),
color: ColorTheme::light(),
progress: ProgressTheme::light(),
}
}
pub fn dark() -> Self {
@ -33,7 +30,6 @@ impl Theme {
name: "dark".into(),
common: CommonTheme::dark(),
color: ColorTheme::dark(),
progress: ProgressTheme::dark(),
}
}
}