gpui-kit GitHub

Scenes

animated-number

Builds AnimatedNumber Button

animated-number in the dark theme
studio-dark
animated-number in the light theme
studio-light

The code that drew it

A still frame holds a repeating animation at its first frame and a one-shot at its last, because a still of a moving thing is not reproducible. Run the gallery to review motion.

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();

    let readout = |label: &'static str, number: AnimatedNumber| {
        div()
            .column()
            .gap(px(theme.spacing.xs))
            .child(
                div()
                    .text_size(px(theme.typography.caption.size))
                    .text_color(theme.colors.text_muted)
                    .child(label),
            )
            .child(number)
    };

    stack(&theme)
        .child(
            row(&theme)
                .gap(px(theme.spacing.xl))
                .items_start()
                .child(readout(
                    "Runs this week",
                    AnimatedNumber::new("scene.number.runs", runs).format(grouped),
                ))
                .child(readout(
                    "Median duration",
                    AnimatedNumber::new("scene.number.seconds", seconds)
                        .format(|value| format!("{value:.1}s")),
                )),
        )
        .child(
            row(&theme).child(
                Button::new("scene.number.recount")
                    .label("Recount")
                    .secondary()
                    .on_click(|_, cx| {
                        cx.update_global::<SceneCounts, ()>(|counts, _| {
                            counts.runs += 318.0;
                            counts.seconds += 4.7;
                        });
                        cx.refresh_windows();
                    }),
            ),
        )
        .child(
            div()
                .text_size(px(theme.typography.caption.size))
                .text_color(theme.colors.text_muted)
                .child("The published value is the target, from the frame it changes."),
        )
        .into_any_element()
}