freya_components/
progressbar.rs1use freya_animation::{
2 easing::Function,
3 hook::{
4 Ease,
5 use_animation_transition,
6 },
7 prelude::AnimNum,
8};
9use freya_core::prelude::*;
10use torin::{
11 prelude::Alignment,
12 size::Size,
13};
14
15use crate::{
16 get_theme,
17 theming::component_themes::ProgressBarThemePartial,
18};
19
20#[cfg_attr(feature = "docs",
39 doc = embed_doc_image::embed_image!("progressbar", "images/gallery_progressbar.png")
40)]
41#[derive(Clone, PartialEq)]
42pub struct ProgressBar {
43 pub(crate) theme: Option<ProgressBarThemePartial>,
44 width: Size,
45 show_progress: bool,
46 progress: f32,
47 key: DiffKey,
48}
49
50impl KeyExt for ProgressBar {
51 fn write_key(&mut self) -> &mut DiffKey {
52 &mut self.key
53 }
54}
55
56impl ProgressBar {
57 pub fn new(progress: impl Into<f32>) -> Self {
58 Self {
59 width: Size::fill(),
60 theme: None,
61 show_progress: true,
62 progress: progress.into(),
63 key: DiffKey::None,
64 }
65 }
66
67 pub fn width(mut self, width: impl Into<Size>) -> Self {
68 self.width = width.into();
69 self
70 }
71
72 pub fn show_progress(mut self, show_progress: bool) -> Self {
73 self.show_progress = show_progress;
74 self
75 }
76}
77
78impl Component for ProgressBar {
79 fn render(&self) -> impl IntoElement {
80 let progressbar_theme = get_theme!(&self.theme, progressbar);
81
82 let progress = use_reactive(&self.progress.clamp(0., 100.));
83 let animation = use_animation_transition(progress, |from, to| {
84 AnimNum::new(from, to)
85 .time(500)
86 .ease(Ease::Out)
87 .function(Function::Expo)
88 });
89
90 rect()
91 .a11y_alt(format!("Progress {}%", progress()))
92 .a11y_focusable(true)
93 .a11y_role(AccessibilityRole::ProgressIndicator)
94 .horizontal()
95 .width(self.width.clone())
96 .height(Size::px(progressbar_theme.height))
97 .corner_radius(99.)
98 .overflow(Overflow::Clip)
99 .background(progressbar_theme.background)
100 .border(
101 Border::new()
102 .width(1.)
103 .alignment(BorderAlignment::Outer)
104 .fill(progressbar_theme.background),
105 )
106 .font_size(13.)
107 .child(
108 rect()
109 .horizontal()
110 .width(Size::percent(&*animation.read()))
111 .cross_align(Alignment::Center)
112 .height(Size::fill())
113 .corner_radius(99.)
114 .background(progressbar_theme.progress_background)
115 .child(
116 label()
117 .width(Size::fill())
118 .color(progressbar_theme.color)
119 .text_align(TextAlign::Center)
120 .text(format!("{}%", self.progress))
121 .max_lines(1),
122 ),
123 )
124 }
125
126 fn render_key(&self) -> DiffKey {
127 self.key.clone().or(self.default_key())
128 }
129}