GPUI Box GitHub

Components / interaction

SwipeActions view

A stable row with two optional action trays. Revealing is transient visual state, never selection or deletion. Vertical gestures remain scroll gestures.

A view survives a frame. Hold it in an Entity with cx.new(..) and reach it with .update(..).

use gpui_kit::interaction::swipe::SwipeActions;

Reviewed in swipe-actions.

Construct
new(ident: impl Into<Ident>, reveal_label: impl Into<SharedString>) -> Self
Commands

Need a Context, so they need a view.

set_content(body: Option<Body>, cx: &mut Context<Self>)
set_actions(side: SwipeSide, actions: Vec<SheetAction>, cx: &mut Context<Self>)
set_state(state: SheetActionState, cx: &mut Context<Self>)
set_enabled(enabled: bool, cx: &mut Context<Self>)
reveal(side: Option<SwipeSide>, cx: &mut Context<Self>) -> bool
Queries

Only answer; they change nothing.

revealed() -> Option<SwipeSide>
Reports

The variants of the event it emits. It never applies the change itself.

  • Revealed
  • ActionRequested
Example · swipe-actions
fn swipe_actions(_window: &mut Window, cx: &mut App) -> AnyElement {
    if !cx.has_global::<SceneSwipe>() {
        let mut views = Vec::new();
        for (id, side, state) in [
            ("closed", None, SheetActionState::Ready),
            ("left", Some(SwipeSide::Left), SheetActionState::Ready),
            (
                "right",
                Some(SwipeSide::Right),
                SheetActionState::Error("Deletion failed; row retained".into()),
            ),
            (
                "pending",
                Some(SwipeSide::Right),
                SheetActionState::Pending("Waiting for caller".into()),
            ),
        ] {
            let view = cx.new(|_| SwipeActions::new(format!("scene.swipe.{id}"), "Actions"));
            view.update(cx, |swipe, cx| {
                let mut remove = SheetAction::new("remove", "Delete");
                remove.destructive = true;
                swipe.set_actions(SwipeSide::Left, vec![SheetAction::new("pin", "Pin")], cx);
                swipe.set_actions(SwipeSide::Right, vec![remove], cx);
                swipe.set_content(
                    Some(Rc::new(move |_, cx| {
                        let theme = cx.theme().clone();
                        div()
                            .h(px(64.0))
                            .column()
                            .justify_center()
                            .child(crate::foundation::text(
                                &theme,
                                TypeScale::Label,
                                "Project notes · fixture",
                            ))
                            .child(crate::foundation::text(
                                &theme,
                                TypeScale::Body,
                                "Last verified content remains visible",
                            ))
                            .semantic_in(
                                cx,
                                NodeSpec::new(format!("scene.swipe.{id}.content"), Role::Group)
                                    .text("Project notes · fixture"),
                            )
                            .into_any_element()
                    })),
                    cx,
                );
                swipe.reveal(side, cx);
                swipe.set_state(state, cx);
            });
            views.push(view);
        }
        cx.set_global(SceneSwipe(views));
    }
    let theme = cx.theme().clone();
    stack(&theme)
        .w(px(580.0))
        .child(caption(
            &theme,
            "Reveal is not activation · physical left and right trays",
        ))
        .children(cx.global::<SceneSwipe>().0.iter().cloned())
        .into_any_element()
}

Source: crates/gpui-kit/src/interaction/swipe.rs