gpuikit/elements/
progress.rs1use crate::theme::{ActiveTheme, Themeable};
2use gpui::{
3 App, IntoElement, ParentElement, Pixels, RenderOnce, Styled, Window, div,
4 prelude::FluentBuilder, px, relative,
5};
6
7pub fn progress(value: f32) -> Progress {
8 Progress::new(value)
9}
10
11#[derive(Clone, Copy, Default)]
12pub enum ProgressVariant {
13 #[default]
14 Default,
15 Success,
16 Danger,
17}
18
19#[derive(IntoElement)]
20pub struct Progress {
21 value: f32,
22 variant: ProgressVariant,
23 height: Option<Pixels>,
24 width: Option<Pixels>,
25}
26
27impl Progress {
28 pub fn new(value: f32) -> Self {
29 Self {
30 value: value.clamp(0.0, 1.0),
31 variant: ProgressVariant::Default,
32 height: None,
33 width: None,
34 }
35 }
36
37 pub fn variant(mut self, variant: ProgressVariant) -> Self {
38 self.variant = variant;
39 self
40 }
41
42 pub fn height(mut self, height: impl Into<Pixels>) -> Self {
43 self.height = Some(height.into());
44 self
45 }
46
47 pub fn width(mut self, width: impl Into<Pixels>) -> Self {
48 self.width = Some(width.into());
49 self
50 }
51}
52
53impl RenderOnce for Progress {
54 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
55 let theme = cx.theme();
56 let height = self.height.unwrap_or(px(8.0));
57 let border_radius = height / 2.0;
58
59 let fill_color = match self.variant {
60 ProgressVariant::Default => theme.accent(),
61 ProgressVariant::Success => theme.accent(),
62 ProgressVariant::Danger => theme.danger(),
63 };
64
65 let fill_width = self.value.max(0.02);
66
67 div()
68 .w_full()
69 .when_some(self.width, |this, width| this.w(width))
70 .h(height)
71 .bg(theme.surface_secondary())
72 .rounded(border_radius)
73 .overflow_hidden()
74 .child(
75 div()
76 .h_full()
77 .w(relative(fill_width))
78 .bg(fill_color)
79 .rounded(border_radius),
80 )
81 }
82}