add progress
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
//! The progress bar: determinate fill or an indeterminate sweep.
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use gpui::prelude::FluentBuilder as _;
|
||||
use gpui::{
|
||||
Animation, AnimationExt as _, App, ElementId, InteractiveElement as _, IntoElement,
|
||||
ParentElement as _, RenderOnce, Role, SharedString, StatefulInteractiveElement as _,
|
||||
Styled as _, Window, div, relative,
|
||||
};
|
||||
use gpui_native_theme::ActiveTheme as _;
|
||||
|
||||
/// A progress bar. With a `value` in `0..=1` it paints a determinate fill.
|
||||
#[derive(IntoElement)]
|
||||
pub struct Progress {
|
||||
id: ElementId,
|
||||
value: f32,
|
||||
indeterminate: bool,
|
||||
a11y_label: Option<SharedString>,
|
||||
}
|
||||
|
||||
impl Progress {
|
||||
/// Creates a determinate progress bar at `value` (`0..=1`).
|
||||
pub fn new<I>(id: I, value: f32) -> Self
|
||||
where
|
||||
I: Into<ElementId>,
|
||||
{
|
||||
Self {
|
||||
id: id.into(),
|
||||
value,
|
||||
indeterminate: false,
|
||||
a11y_label: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sweeps instead of painting a fill, for work of unknown length.
|
||||
pub fn indeterminate(mut self, indeterminate: bool) -> Self {
|
||||
self.indeterminate = indeterminate;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the accessibility label.
|
||||
pub fn accessibility_label<L>(mut self, label: L) -> Self
|
||||
where
|
||||
L: Into<SharedString>,
|
||||
{
|
||||
self.a11y_label = Some(label.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for Progress {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let theme = cx.theme();
|
||||
let colors = theme.colors;
|
||||
let ramps = theme.ramps;
|
||||
let radius = theme.radius;
|
||||
let value = self.value.clamp(0.0, 1.0);
|
||||
|
||||
div()
|
||||
.id(self.id)
|
||||
.w_full()
|
||||
.role(Role::ProgressIndicator)
|
||||
.when_some(self.a11y_label, |progress, label| {
|
||||
progress.aria_label(label)
|
||||
})
|
||||
.when(!self.indeterminate, |progress| {
|
||||
progress
|
||||
.aria_numeric_value(f64::from(value))
|
||||
.aria_min_numeric_value(0.0)
|
||||
.aria_max_numeric_value(1.0)
|
||||
})
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.h_1p5()
|
||||
.rounded(radius.full)
|
||||
.bg(colors.border)
|
||||
.child(if self.indeterminate {
|
||||
div()
|
||||
.h_full()
|
||||
.w(relative(0.3))
|
||||
.rounded(radius.full)
|
||||
.bg(ramps.primary.base)
|
||||
.with_animation(
|
||||
"indeterminate",
|
||||
Animation::new(Duration::from_millis(1500)).repeat(),
|
||||
|pill, delta| pill.ml(relative(delta * 0.7)),
|
||||
)
|
||||
.into_any_element()
|
||||
} else {
|
||||
div()
|
||||
.h_full()
|
||||
.w(relative(value))
|
||||
.rounded(radius.full)
|
||||
.bg(ramps.primary.base)
|
||||
.into_any_element()
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user