gpui_component/sidebar/
group.rs1use crate::{v_flex, ActiveTheme, Collapsible};
2use gpui::{
3 div, prelude::FluentBuilder as _, App, Div, IntoElement, ParentElement, RenderOnce,
4 SharedString, Styled as _, Window,
5};
6
7#[derive(IntoElement)]
9pub struct SidebarGroup<E: Collapsible + IntoElement + 'static> {
10 base: Div,
11 label: SharedString,
12 collapsed: bool,
13 children: Vec<E>,
14}
15
16impl<E: Collapsible + IntoElement> SidebarGroup<E> {
17 pub fn new(label: impl Into<SharedString>) -> Self {
19 Self {
20 base: div().gap_2().flex_col(),
21 label: label.into(),
22 collapsed: false,
23 children: Vec::new(),
24 }
25 }
26
27 pub fn child(mut self, child: E) -> Self {
29 self.children.push(child);
30 self
31 }
32
33 pub fn children(mut self, children: impl IntoIterator<Item = E>) -> Self {
37 self.children.extend(children);
38 self
39 }
40}
41
42impl<E: Collapsible + IntoElement> Collapsible for SidebarGroup<E> {
43 fn is_collapsed(&self) -> bool {
44 self.collapsed
45 }
46
47 fn collapsed(mut self, collapsed: bool) -> Self {
48 self.collapsed = collapsed;
49 self
50 }
51}
52
53impl<E: Collapsible + IntoElement> RenderOnce for SidebarGroup<E> {
54 fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
55 v_flex()
56 .relative()
57 .p_2()
58 .when(!self.collapsed, |this| {
59 this.child(
60 div()
61 .flex_shrink_0()
62 .px_2()
63 .rounded(cx.theme().radius)
64 .text_xs()
65 .text_color(cx.theme().sidebar_foreground.opacity(0.7))
66 .h_8()
67 .child(self.label),
68 )
69 })
70 .child(
71 self.base.children(
72 self.children
73 .into_iter()
74 .map(|child| child.collapsed(self.collapsed)),
75 ),
76 )
77 }
78}