ui/components/
app_shell.rs1use gpui::AnyElement;
2
3use crate::prelude::*;
4
5#[derive(IntoElement, RegisterComponent)]
9pub struct AppShell {
10 navbar: Option<AnyElement>,
11 sidebar: Option<AnyElement>,
12 content: Option<AnyElement>,
13}
14
15impl AppShell {
16 pub fn new() -> Self {
17 Self {
18 navbar: None,
19 sidebar: None,
20 content: None,
21 }
22 }
23
24 pub fn navbar(mut self, navbar: impl IntoElement) -> Self {
25 self.navbar = Some(navbar.into_any_element());
26 self
27 }
28
29 pub fn sidebar(mut self, sidebar: impl IntoElement) -> Self {
30 self.sidebar = Some(sidebar.into_any_element());
31 self
32 }
33
34 pub fn content(mut self, content: impl IntoElement) -> Self {
35 self.content = Some(content.into_any_element());
36 self
37 }
38}
39
40impl Default for AppShell {
41 fn default() -> Self {
42 Self::new()
43 }
44}
45
46impl RenderOnce for AppShell {
47 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
48 v_flex().w_full().h_full().children(self.navbar).child(
49 h_flex()
50 .flex_1()
51 .items_stretch()
52 .children(self.sidebar)
53 .child(div().flex_1().h_full().children(self.content)),
54 )
55 }
56}
57
58impl Component for AppShell {
59 fn scope() -> ComponentScope {
60 ComponentScope::Layout
61 }
62
63 fn description() -> Option<&'static str> {
64 Some("Composes a Navbar (top) and Sidebar (left) around a main content slot.")
65 }
66
67 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
68 Some(
69 div()
70 .h(px(320.))
71 .child(
72 AppShell::new()
73 .navbar(Navbar::new().child(Label::new("Application")))
74 .sidebar(
75 Sidebar::new()
76 .child(SidebarItem::new("shell-home", "Home").active(true))
77 .child(SidebarItem::new("shell-settings", "Settings")),
78 )
79 .content(div().p_6().child(Label::new("Main content area"))),
80 )
81 .into_any_element(),
82 )
83 }
84}