GPUI Box GitHub

Components / overlay

Drawer view

A panel anchored to one side of the window.

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

use gpui_kit::overlay::Drawer;

Reviewed in drawer.

Construct
new(ident: impl Into<Ident>, _window: &mut Window, cx: &mut Context<Self>) -> Self
Options

Chain onto the value.

edge(edge: Edge) -> Self
avoid_insets(avoid: bool) -> Self
close_control_size(size: ControlSize) -> Self
body_padding_x(padding: Space) -> Self
size(size: f32) -> Self
title(title: impl Into<SharedString>) -> Self
description(description: impl Into<SharedString>) -> Self
content(body: impl Fn(&mut Window, &mut App) -> AnyElement + 'static) -> Self
footer(footer: impl Fn(&mut Window, &mut App) -> AnyElement + 'static) -> Self
dismissable(dismissable: bool) -> Self
resizable(resizable: bool) -> Self
focus_stops(stops: impl IntoIterator<Item = FocusHandle>) -> Self
Commands

Need a Context, so they need a view.

set_avoid_insets(avoid: bool, cx: &mut Context<Self>)
set_size(size: f32, cx: &mut Context<Self>)
set_focus_stops(stops: impl IntoIterator<Item = FocusHandle>, cx: &mut Context<Self>)
set_title(title: impl Into<SharedString>, cx: &mut Context<Self>)
set_edge(edge: Edge, cx: &mut Context<Self>)
set_description(description: Option<SharedString>, cx: &mut Context<Self>)
set_content(body: Option<Body>, cx: &mut Context<Self>)
set_footer(footer: Option<Body>, cx: &mut Context<Self>)
set_dismissable(dismissable: bool, cx: &mut Context<Self>)
set_resizable(resizable: bool, cx: &mut Context<Self>)
open(window: &mut Window, cx: &mut Context<Self>)
close(window: &mut Window, cx: &mut Context<Self>)
dismiss(window: &mut Window, cx: &mut Context<Self>)
settle(cx: &mut Context<Self>)
Queries

Only answer; they change nothing.

is_open() -> bool
is_dismissable() -> bool
is_rendered() -> bool
Reports

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

  • Opened
  • Dismissed
  • Closed
  • ResizeRequested
Example · drawer
fn drawer(window: &mut Window, cx: &mut App) -> AnyElement {
    if !cx.has_global::<SceneDrawer>() {
        let filters = cx.new(|cx| {
            Drawer::new("scene.drawer.filters", window, cx)
                .edge(Edge::Right)
                .size(320.0)
                .resizable(true)
                .title("Filter runs")
                .description("The drawer reports what was chosen. The host applies it.")
                .content(|_, cx| {
                    let theme = cx.theme().clone();
                    let group = |heading: &'static str, rows: gpui::Div| {
                        div()
                            .column()
                            .gap(px(theme.space(Space::Sm)))
                            .child(
                                crate::foundation::text(&theme, TypeScale::Label, heading)
                                    .text_tone(&theme, TextTone::Muted),
                            )
                            .child(rows.column().gap(px(theme.space(Space::Sm))))
                    };
                    div()
                        .column()
                        .gap(px(theme.space(Space::Lg)))
                        .child(group(
                            "Outcome",
                            div()
                                .child(
                                    Checkbox::new("scene.drawer.failed")
                                        .label("Failed runs only")
                                        .checked(true)
                                        .on_change(|_, _, _| {}),
                                )
                                .child(
                                    Checkbox::new("scene.drawer.cancelled")
                                        .label("Include cancelled")
                                        .on_change(|_, _, _| {}),
                                ),
                        ))
                        .child(group(
                            "Ownership",
                            div()
                                .child(
                                    Checkbox::new("scene.drawer.mine")
                                        .label("Started by me")
                                        .on_change(|_, _, _| {}),
                                )
                                .child(
                                    Checkbox::new("scene.drawer.watching")
                                        .label("Repositories I watch")
                                        .checked(true)
                                        .on_change(|_, _, _| {}),
                                ),
                        ))
                        .child(group(
                            "Window",
                            div()
                                .child(
                                    Checkbox::new("scene.drawer.today")
                                        .label("Today")
                                        .checked(true)
                                        .on_change(|_, _, _| {}),
                                )
                                .child(
                                    Checkbox::new("scene.drawer.week")
                                        .label("This week")
                                        .on_change(|_, _, _| {}),
                                ),
                        ))
                        .into_any_element()
                })
                // Two controls, sized to their labels and pinned to the
                // reading edge: a full-width primary slab is the loudest
                // thing on the page and says the drawer has one exit.
                .footer(|_, cx| {
                    let theme = cx.theme().clone();
                    div()
                        .row()
                        .justify_end()
                        .gap(px(theme.space(Space::Sm)))
                        .child(
                            Button::new("scene.drawer.cancel")
                                .label("Cancel")
                                .secondary()
                                .on_click(|_, _| {}),
                        )
                        .child(
                            Button::new("scene.drawer.apply")
                                .label("Apply")
                                .primary()
                                .on_click(|_, _| {}),
                        )
                        .into_any_element()
                })
        });
        filters.update(cx, |drawer, cx| {
            drawer.open(window, cx);
            drawer.settle(cx);
        });
        cx.set_global(SceneDrawer { filters });
    }
    let filters = cx.global::<SceneDrawer>().filters.clone();
    let theme = cx.theme().clone();

    stack(&theme)
        .w(px(620.0))
        .h(px(400.0))
        .child(page_behind(&theme, "Runs"))
        .child(filters)
        .into_any_element()
}

Source: crates/gpui-kit/src/overlay/drawer.rs