gpui_component/sidebar/
header.rs

1use gpui::{
2    div, prelude::FluentBuilder as _, AnyElement, Div, InteractiveElement, IntoElement,
3    ParentElement, RenderOnce, StyleRefinement, Styled,
4};
5
6use crate::{menu::DropdownMenu, ActiveTheme as _, Collapsible, Selectable, StyledExt};
7
8/// Header for the [`super::Sidebar`]
9#[derive(IntoElement)]
10pub struct SidebarHeader {
11    base: Div,
12    style: StyleRefinement,
13    children: Vec<AnyElement>,
14    selected: bool,
15    collapsed: bool,
16}
17
18impl SidebarHeader {
19    /// Create a new [`SidebarHeader`].
20    pub fn new() -> Self {
21        Self {
22            base: div(),
23            style: StyleRefinement::default(),
24            children: Vec::new(),
25            selected: false,
26            collapsed: false,
27        }
28    }
29}
30
31impl Default for SidebarHeader {
32    fn default() -> Self {
33        Self::new()
34    }
35}
36
37impl Selectable for SidebarHeader {
38    fn selected(mut self, selected: bool) -> Self {
39        self.selected = selected;
40        self
41    }
42
43    fn is_selected(&self) -> bool {
44        self.selected
45    }
46}
47
48impl Collapsible for SidebarHeader {
49    fn is_collapsed(&self) -> bool {
50        self.collapsed
51    }
52
53    fn collapsed(mut self, collapsed: bool) -> Self {
54        self.collapsed = collapsed;
55        self
56    }
57}
58
59impl ParentElement for SidebarHeader {
60    fn extend(&mut self, elements: impl IntoIterator<Item = gpui::AnyElement>) {
61        self.children.extend(elements);
62    }
63}
64
65impl Styled for SidebarHeader {
66    fn style(&mut self) -> &mut gpui::StyleRefinement {
67        &mut self.style
68    }
69}
70
71impl InteractiveElement for SidebarHeader {
72    fn interactivity(&mut self) -> &mut gpui::Interactivity {
73        self.base.interactivity()
74    }
75}
76
77impl DropdownMenu for SidebarHeader {}
78
79impl RenderOnce for SidebarHeader {
80    fn render(self, _: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement {
81        self.base
82            .id("sidebar-header")
83            .h_flex()
84            .gap_2()
85            .p_2()
86            .w_full()
87            .justify_between()
88            .rounded(cx.theme().radius)
89            .refine_style(&self.style)
90            .hover(|this| {
91                this.bg(cx.theme().sidebar_accent)
92                    .text_color(cx.theme().sidebar_accent_foreground)
93            })
94            .when(self.selected, |this| {
95                this.bg(cx.theme().sidebar_accent)
96                    .text_color(cx.theme().sidebar_accent_foreground)
97            })
98            .children(self.children)
99    }
100}