add progress
This commit is contained in:
@@ -22,3 +22,6 @@ pub mod link;
|
|||||||
|
|
||||||
#[cfg(feature = "slider")]
|
#[cfg(feature = "slider")]
|
||||||
pub mod slider;
|
pub mod slider;
|
||||||
|
|
||||||
|
#[cfg(feature = "progress")]
|
||||||
|
pub mod progress;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
use gpui::{ParentElement as _, Render, Styled as _, TestAppContext, Window, div};
|
||||||
|
use gpui_native_core::progress::Progress;
|
||||||
|
use gpui_native_theme::Theme;
|
||||||
|
|
||||||
|
struct Harness;
|
||||||
|
|
||||||
|
impl Render for Harness {
|
||||||
|
fn render(
|
||||||
|
&mut self,
|
||||||
|
_window: &mut Window,
|
||||||
|
_cx: &mut gpui::Context<Self>,
|
||||||
|
) -> impl gpui::IntoElement {
|
||||||
|
div()
|
||||||
|
.size_full()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.gap_2()
|
||||||
|
.child(Progress::new("test-progress", 0.6).accessibility_label("Upload"))
|
||||||
|
.child(
|
||||||
|
Progress::new("test-progress-indeterminate", 0.0)
|
||||||
|
.indeterminate(true)
|
||||||
|
.accessibility_label("Working"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn determinate_and_indeterminate_bars_draw_headlessly(cx: &mut TestAppContext) {
|
||||||
|
cx.update(Theme::init);
|
||||||
|
let (view, visual) = cx.add_window_view(|_, _| Harness);
|
||||||
|
let _ = view;
|
||||||
|
visual.run_until_parked();
|
||||||
|
visual.update(|window, cx| {
|
||||||
|
window.draw(cx).clear(cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ use gpui_native_core::button::{Button, ButtonVariant};
|
|||||||
use gpui_native_core::checkbox::Checkbox;
|
use gpui_native_core::checkbox::Checkbox;
|
||||||
use gpui_native_core::common::{h_flex, v_flex};
|
use gpui_native_core::common::{h_flex, v_flex};
|
||||||
use gpui_native_core::link::Link;
|
use gpui_native_core::link::Link;
|
||||||
|
use gpui_native_core::progress::Progress;
|
||||||
use gpui_native_core::radio::{Radio, RadioGroup};
|
use gpui_native_core::radio::{Radio, RadioGroup};
|
||||||
use gpui_native_core::slider::Slider;
|
use gpui_native_core::slider::Slider;
|
||||||
use gpui_native_core::switch::Switch;
|
use gpui_native_core::switch::Switch;
|
||||||
@@ -392,6 +393,22 @@ impl Render for Gallery {
|
|||||||
.child(format!("volume: {}", self.volume)),
|
.child(format!("volume: {}", self.volume)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
v_flex()
|
||||||
|
.gap_2()
|
||||||
|
.child(section_label(
|
||||||
|
"progress · native refs — NSProgressIndicator, WinUI ProgressBar, Adwaita ProgressBar, Breeze",
|
||||||
|
colors,
|
||||||
|
))
|
||||||
|
.child(Progress::new("progress-25", 0.25).accessibility_label("Quarter"))
|
||||||
|
.child(Progress::new("progress-60", 0.6).accessibility_label("Most"))
|
||||||
|
.child(Progress::new("progress-90", 0.9).accessibility_label("Nearly"))
|
||||||
|
.child(
|
||||||
|
Progress::new("progress-indeterminate", 0.0)
|
||||||
|
.indeterminate(true)
|
||||||
|
.accessibility_label("Working"),
|
||||||
|
),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
|
|||||||
Reference in New Issue
Block a user