list_section_header.rs

 1use crate::prelude::{InteractionState, ToggleState};
 2use crate::theme::theme;
 3use crate::tokens::token;
 4use crate::{icon, label, IconAsset, LabelColor, LabelSize};
 5use gpui2::style::{StyleHelpers, Styleable};
 6use gpui2::{elements::div, IntoElement};
 7use gpui2::{Element, ParentElement, ViewContext};
 8
 9#[derive(Element, Clone, Copy)]
10pub struct ListSectionHeader {
11    label: &'static str,
12    left_icon: Option<IconAsset>,
13    state: InteractionState,
14    toggle: Option<ToggleState>,
15}
16
17pub fn list_section_header(label: &'static str) -> ListSectionHeader {
18    ListSectionHeader {
19        label,
20        left_icon: None,
21        state: InteractionState::default(),
22        toggle: None,
23    }
24}
25
26impl ListSectionHeader {
27    pub fn set_toggle(mut self, toggle: ToggleState) -> Self {
28        self.toggle = Some(toggle);
29        self
30    }
31
32    pub fn left_icon(mut self, left_icon: Option<IconAsset>) -> Self {
33        self.left_icon = left_icon;
34        self
35    }
36
37    pub fn state(mut self, state: InteractionState) -> Self {
38        self.state = state;
39        self
40    }
41
42    fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
43        let theme = theme(cx);
44        let token = token();
45
46        let disclosure_control = match self.toggle {
47            Some(ToggleState::NotToggled) => Some(div().child(icon(IconAsset::ChevronRight))),
48            Some(ToggleState::Toggled) => Some(div().child(icon(IconAsset::ChevronDown))),
49            None => Some(div()),
50        };
51
52        div()
53            .flex()
54            .flex_1()
55            .w_full()
56            .fill(theme.middle.base.default.background)
57            .hover()
58            .fill(theme.middle.base.hovered.background)
59            .active()
60            .fill(theme.middle.base.pressed.background)
61            .relative()
62            .py_1()
63            .child(
64                div()
65                    .h_6()
66                    .px_2()
67                    .flex()
68                    .flex_1()
69                    .w_full()
70                    .gap_1()
71                    .items_center()
72                    .justify_between()
73                    .child(
74                        div()
75                            .flex()
76                            .gap_1()
77                            .items_center()
78                            .children(self.left_icon.map(|i| icon(i)))
79                            .child(
80                                label(self.label.clone())
81                                    .color(LabelColor::Muted)
82                                    .size(LabelSize::Small),
83                            ),
84                    )
85                    .children(disclosure_control),
86            )
87    }
88}