mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-23 06:19:22 -05:00
Feat/progress circle (#124)
* feat: Adds ProgressCircle component * feat: ProgressCircle adds children prop * feat: ProgressCircle adds class and size prop
This commit is contained in:
parent
0f499a67a9
commit
a44d0a9c38
4 changed files with 176 additions and 7 deletions
|
@ -19,11 +19,40 @@ view! {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Circle
|
||||||
|
|
||||||
|
```rust demo
|
||||||
|
let percentage = create_rw_signal(0.0f32);
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<Space>
|
||||||
|
<ProgressCircle percentage/>
|
||||||
|
<ProgressCircle percentage color=ProgressColor::Success/>
|
||||||
|
<ProgressCircle percentage color=ProgressColor::Warning/>
|
||||||
|
<ProgressCircle percentage color=ProgressColor::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>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Progress Props
|
### Progress Props
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| ------------------- | ----------------------------------------- | ------------------------------------- | ------------------------------ |
|
| --- | --- | --- | --- |
|
||||||
| percentage | `MaybeSignal<f32>` | `Default::default()` | Percentage value. |
|
| percentage | `MaybeSignal<f32>` | `Default::default()` | Percentage value. |
|
||||||
| color | `MaybeSignal<ProgressColor>` | `ProgressColor::Primary` | Progress color. |
|
| color | `MaybeSignal<ProgressColor>` | `ProgressColor::Primary` | Progress color. |
|
||||||
| show_indicator | `MaybeSignal<bool>` | `true` | Whether to display indicators. |
|
| show_indicator | `MaybeSignal<bool>` | `true` | Whether to display indicators. |
|
||||||
| indicator_placement | `MaybeSignal<ProgressIndicatorPlacement>` | `ProgressIndicatorPlacement::Outside` | Indicator placement. |
|
| indicator_placement | `MaybeSignal<ProgressIndicatorPlacement>` | `ProgressIndicatorPlacement::Outside` | Indicator placement. |
|
||||||
|
|
||||||
|
### ProgressCircle Props
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| class | `OptionalProp<MaybeSignal<String>>` | `Default::default()` | Addtional classes for the progress element. |
|
||||||
|
| percentage | `MaybeSignal<f32>` | `Default::default()` | Percentage value. |
|
||||||
|
| color | `MaybeSignal<ProgressColor>` | `ProgressColor::Primary` | ProgressCircle color. |
|
||||||
|
| size | `MaybeSignal<Stringr>` | `120px` | ProgressCircle size. |
|
||||||
|
| children | `Option<Children>` | `None` | ProgressCircle's content. |
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
mod progress_circle;
|
||||||
mod theme;
|
mod theme;
|
||||||
|
|
||||||
|
pub use progress_circle::ProgressCircle;
|
||||||
|
pub use theme::ProgressTheme;
|
||||||
|
|
||||||
use crate::{use_theme, utils::mount_style, Theme};
|
use crate::{use_theme, utils::mount_style, Theme};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
pub use theme::ProgressTheme;
|
|
||||||
|
|
||||||
#[derive(Default, Clone, PartialEq)]
|
#[derive(Default, Clone, PartialEq)]
|
||||||
pub enum ProgressIndicatorPlacement {
|
pub enum ProgressIndicatorPlacement {
|
||||||
|
|
30
thaw/src/progress/progress-circle.css
Normal file
30
thaw/src/progress/progress-circle.css
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
.thaw-progress-circle {
|
||||||
|
width: var(--thaw-size);
|
||||||
|
height: var(--thaw-size);
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-progress-circle__fill {
|
||||||
|
transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
stroke 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
stroke-dasharray 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-progress-circle__fill--empty {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-progress-circle__content {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateX(-50%) translateY(-50%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-progress-circle__content--text {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
107
thaw/src/progress/progress_circle.rs
Normal file
107
thaw/src/progress/progress_circle.rs
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
use super::ProgressColor;
|
||||||
|
use crate::{
|
||||||
|
use_theme,
|
||||||
|
utils::{class_list::class_list, mount_style, OptionalProp},
|
||||||
|
Theme,
|
||||||
|
};
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
#[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, 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;
|
||||||
|
|
||||||
|
let radius = 50;
|
||||||
|
let begin_position_x = 0;
|
||||||
|
let begin_position_y = radius;
|
||||||
|
let end_position_x = 0;
|
||||||
|
let end_position_y = 2 * radius;
|
||||||
|
let center_x = 50 + stroke_width / 2;
|
||||||
|
let rail_path = format!("M {center_x},{center_x} m {begin_position_x},{begin_position_y} a {radius},{radius} 0 1 1 {end_position_x},{} a {radius},{radius} 0 1 1 {},{end_position_y}", -end_position_y, -end_position_x);
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
format!(
|
||||||
|
"{}px {}px",
|
||||||
|
f64::from(percentage / 100.0) * len,
|
||||||
|
view_box_width * 8
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let fill_stroke_color =
|
||||||
|
Memo::new(move |_| theme.with(|theme| color.get().theme_background_color(theme)));
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<div
|
||||||
|
class=class_list!["thaw-progress-circle", class.map(|c| move || c.get())]
|
||||||
|
role="progressbar"
|
||||||
|
aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow=move || percentage.get()
|
||||||
|
style=("--thaw-fill-color", move || fill_stroke_color.get())
|
||||||
|
style=("--thaw-size", move || size.get())
|
||||||
|
|
||||||
|
>
|
||||||
|
<svg viewBox="0 0 107 107">
|
||||||
|
<g>
|
||||||
|
<path
|
||||||
|
d=rail_path
|
||||||
|
stroke-width=stroke_width
|
||||||
|
stroke-linecap="round"
|
||||||
|
fill="none"
|
||||||
|
style:stroke=move || rail_stroke_color.get()
|
||||||
|
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)
|
||||||
|
d=fill_path
|
||||||
|
stroke-width=stroke_width
|
||||||
|
stroke-linecap="round"
|
||||||
|
fill="none"
|
||||||
|
style:stroke="var(--thaw-fill-color)"
|
||||||
|
style:stroke-dasharray=move || fill_stroke_dasharray.get()
|
||||||
|
></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
{
|
||||||
|
if let Some(children) = children {
|
||||||
|
view! {
|
||||||
|
<div class="thaw-progress-circle__content">
|
||||||
|
{children()}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
view! {
|
||||||
|
<div class="thaw-progress-circle__content thaw-progress-circle__content--text">
|
||||||
|
{move || percentage.get()}"%"
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue