motion-flip
Builds Badge Button Card ListRow


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 motion_flip(window: &mut Window, cx: &mut App) -> AnyElement {
if !cx.has_global::<SceneQueue>() {
cx.set_global(SceneQueue {
steps: vec![
("render", "Render frames"),
("upload", "Upload artifacts"),
("verify", "Verify checksums"),
("publish", "Publish release"),
],
});
}
let steps = cx.global::<SceneQueue>().steps.clone();
let theme = cx.theme().clone();
let mut queue = Card::new().id("scene.motion.queue");
for (index, (id, label)) in steps.iter().enumerate() {
let ident = format!("scene.motion.{id}");
let handle = flip(ident.clone(), cx);
queue = queue.child(
ListRow::new()
.id(ident)
.child(div().flex_1().child(*label))
.child(Badge::new(format!("{}", index + 1)).neutral())
.flip(&handle, window, cx),
);
}
stack(&theme)
.w(px(420.0))
.child(
row(&theme).child(
Button::new("scene.motion.reorder")
.label("Move the last step first")
.secondary()
.on_click(|_, cx| {
cx.update_global::<SceneQueue, ()>(|queue, _| queue.steps.rotate_right(1));
cx.refresh_windows();
}),
),
)
.child(queue)
.child(
div()
.text_size(px(theme.typography.caption.size))
.text_color(theme.colors.text_muted)
.child("Rows land in their new slot at once and slide into it."),
)
.into_any_element()
}