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()
}