Skip to main content

gpuikit/elements/
progress.rs

1use 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}