gpui-kit GitHub

Scenes

drag-list

Builds List

drag-list in the dark theme
studio-dark
drag-list 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 drag_list(_window: &mut Window, cx: &mut App) -> AnyElement {
    let theme = cx.theme().clone();
    let carried = fixture_record(4);
    let anchor = fixture_record(1);
    // A capture cannot photograph a gesture, so the drag is placed by hand.
    // Staging fixes the ghost, the indicator, and the open slot, and takes the
    // pointer and the spring out of the picture.
    dnd::stage(
        StagedDrag::new(DragItem::new(
            "scene.drag.records",
            carried.0.clone(),
            carried.1.clone(),
        ))
        .landing(
            "scene.drag.records",
            DropPosition::Before(anchor.0.clone()),
            Some(1),
            true,
        ),
        cx,
    );

    stack(&theme)
        .w(px(420.0))
        .child(caption(
            &theme,
            SharedString::from(format!("{} moving before {}", carried.1, anchor.1)),
        ))
        .child(
            div()
                .relative()
                .hairline(&theme)
                .radius(&theme, Radius::Card)
                .overflow_hidden()
                .child(
                    List::new("scene.drag.records", 6, |index, _, _| {
                        let (id, label) = fixture_record(index);
                        ListItem::new(id, label.clone()).text(label)
                    })
                    // A row slides without its layout slot moving, so the
                    // viewport is one row taller than the rows it holds and
                    // the open slot has somewhere to be.
                    .visible_rows(7)
                    .reorderable(true)
                    .on_select(|_, _, _| {})
                    .on_reorder(|_, _, _| {}),
                )
                .children(
                    dnd::staged_ghost(cx)
                        .map(|ghost| div().absolute().left(px(96.0)).top(px(18.0)).child(ghost)),
                ),
        )
        .into_any_element()
}