Components / display
AnimatedNumber builder
A numeric readout that animates between values.
A builder is RenderOnce. Construct and mount it in one expression.
use gpui_kit::display::animated_number::AnimatedNumber;
Reviewed in animated-number.
Construct
new(ident: impl Into<Ident>, value: f64) -> Self
Options
Chain onto the value.
format(format: impl Fn(f64) -> String + 'static) -> Self
spec(spec: MotionSpec) -> Self
type_scale(scale: TypeScale) -> Self
Example · animated-number
fn animated_number(_window: &mut Window, cx: &mut App) -> AnyElement {
if !cx.has_global::<SceneCounts>() {
cx.set_global(SceneCounts {
runs: 1204.0,
seconds: 18.4,
});
}
let counts = cx.global::<SceneCounts>();
let (runs, seconds) = (counts.runs, counts.seconds);
let theme = cx.theme().clone();
// A readout is a reading, so it is drawn as one: the same card, caption
// and hierarchy a KPI gets. A number floating on the canvas beside its
// label is a debug print of the value, not a report of it.
let readout = |label: &'static str, detail: &'static str, number: AnimatedNumber| {
div()
.column()
.flex_1()
.min_w_0()
.gap(px(theme.space(Space::Xs)))
.p(px(theme.space(Space::Md)))
.card_surface(&theme, CardVariant::Filled)
.child(
crate::foundation::text(&theme, TypeScale::Caption, label)
.text_tone(&theme, TextTone::Muted),
)
.child(number)
.child(
crate::foundation::text(&theme, TypeScale::Caption, detail)
.text_tone(&theme, TextTone::Faint),
)
};
stack(&theme)
.w(px(520.0))
.child(caption(
&theme,
"the published value is the target, from the frame it changes",
))
.child(
div()
.row()
.items_stretch()
.w_full()
.gap(px(theme.space(Space::Md)))
.child(readout(
"Runs this week",
"counted by the host",
AnimatedNumber::new("scene.number.runs", runs)
.format(grouped)
.type_scale(TypeScale::Title),
))
.child(readout(
"Median duration",
"one decimal, the host's choice",
AnimatedNumber::new("scene.number.seconds", seconds)
.format(|value| format!("{value:.1}s"))
.type_scale(TypeScale::Title),
)),
)
.child(
div().row().child(
Button::new("scene.number.recount")
.label("Recount")
.on_click(|_, cx| {
cx.update_global::<SceneCounts, ()>(|counts, _| {
counts.runs += 318.0;
counts.seconds += 4.7;
});
cx.refresh_windows();
}),
),
)
.into_any_element()
}