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="/message-bar" view=MessageBarMdPage/>
<Route path="/modal" view=ModalMdPage/> <Route path="/modal" view=ModalMdPage/>
<Route path="/popover" view=PopoverMdPage/> <Route path="/popover" view=PopoverMdPage/>
<Route path="/progress" view=ProgressMdPage/> <Route path="/progress-bar" view=ProgressBarMdPage/>
<Route path="/radio" view=RadioMdPage/> <Route path="/radio" view=RadioMdPage/>
<Route path="/scrollbar" view=ScrollbarMdPage/> <Route path="/scrollbar" view=ScrollbarMdPage/>
// <Route path="/select" view=SelectMdPage/> // <Route path="/select" view=SelectMdPage/>

View file

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

View file

@ -1,19 +1,17 @@
# Progress # ProgressBar
```rust demo ```rust demo
let percentage = create_rw_signal(0.0f32); let value = RwSignal::new(0.0);
view! { view! {
<Space vertical=true> <Space vertical=true>
<Progress percentage show_indicator=false/> <ProgressBar value/>
<Progress percentage/> <ProgressBar value color=ProgressBarColor::Success/>
<Progress percentage indicator_placement=ProgressIndicatorPlacement::Inside/> <ProgressBar value color=ProgressBarColor::Warning/>
<Progress percentage color=ProgressColor::Success/> <ProgressBar value color=ProgressBarColor::Error/>
<Progress percentage color=ProgressColor::Warning/>
<Progress percentage color=ProgressColor::Error/>
<Space> <Space>
<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 |_| percentage.update(|v| *v += 10.0)>"+10%"</Button> <Button on_click=move |_| value.update(|v| *v += 0.1)>"+10%"</Button>
</Space> </Space>
</Space> </Space>
} }
@ -22,18 +20,18 @@ view! {
### Circle ### Circle
```rust demo ```rust demo
let percentage = create_rw_signal(0.0f32); let value = RwSignal::new(0.0);
view! { view! {
<Space> <Space>
<ProgressCircle percentage/> <ProgressCircle value/>
<ProgressCircle percentage color=ProgressColor::Success/> <ProgressCircle value color=ProgressCircleColor::Success/>
<ProgressCircle percentage color=ProgressColor::Warning/> <ProgressCircle value color=ProgressCircleColor::Warning/>
<ProgressCircle percentage color=ProgressColor::Error/> <ProgressCircle value color=ProgressCircleColor::Error/>
</Space> </Space>
<Space> <Space>
<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 |_| percentage.update(|v| *v += 10.0)>"+10%"</Button> <Button on_click=move |_| value.update(|v| *v += 10.0)>"+10%"</Button>
</Space> </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", "MessageBarMdPage" => "../docs/message_bar/mod.md",
"ModalMdPage" => "../docs/modal/mod.md", "ModalMdPage" => "../docs/modal/mod.md",
"PopoverMdPage" => "../docs/popover/mod.md", "PopoverMdPage" => "../docs/popover/mod.md",
"ProgressMdPage" => "../docs/progress/mod.md", "ProgressBarMdPage" => "../docs/progress_bar/mod.md",
"RadioMdPage" => "../docs/radio/mod.md", "RadioMdPage" => "../docs/radio/mod.md",
"ScrollbarMdPage" => "../docs/scrollbar/mod.md", "ScrollbarMdPage" => "../docs/scrollbar/mod.md",
// "SelectMdPage" => "../docs/select/mod.md", // "SelectMdPage" => "../docs/select/mod.md",

View file

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

View file

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