gpui-kit GitHub

GPUI recipes

Theme boot

let app = gpui_platform::application()
    .with_assets(gpui_kit::assets::Assets);

app.run(|cx| {
    gpui_kit::install(cx);
});

Per-frame semantics

impl Render for View {
    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        self.semantics.begin_frame();
        // Render and attach NodeSpec values.
    }
}

Disabled action

Use action_button; it omits the listener while disabled. If an application builds its own interactive element, apply the same rule explicitly instead of returning early inside an installed callback.

Async refresh with stale data

let mut models = AsyncValue::ready(last_verified);
models.refresh();

// If the host refuses:
models.fail_refresh(error);
// models.value remains visible and status reports the error.

Anchored menu

The trigger owns open state and conditionally adds:

trigger.child(popover::anchored_below(
    "model-menu",
    theme,
    popover::card(theme).children(rows).into_any_element(),
))

The owning view handles focus, keyboard navigation, outside-click dismissal, Escape, and action dispatch.

Capture after settle

In an AsyncApp task:

cx.background_executor().timer(settle).await;
let frame = cx.update(|cx| {
    handle.update(cx, |_, window, _| capture_window(window))
})??;
frame.write_png(path)?;

First wait for the semantic generation produced by the action. A timer by itself is not proof that a frame occurred.