gpui_component/sidebar/
group.rs1use crate::{ActiveTheme, Collapsible, h_flex, v_flex};
2use gpui::{
3 App, Div, IntoElement, ParentElement, RenderOnce, SharedString, Styled as _, Window, div,
4 prelude::FluentBuilder as _,
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 .when(!self.collapsed, |this| {
58 this.child(
59 h_flex()
60 .flex_shrink_0()
61 .px_2()
62 .rounded(cx.theme().radius)
63 .text_xs()
64 .text_color(cx.theme().sidebar_foreground.opacity(0.7))
65 .h_8()
66 .child(self.label),
67 )
68 })
69 .child(
70 self.base.children(
71 self.children
72 .into_iter()
73 .map(|child| child.collapsed(self.collapsed)),
74 ),
75 )
76 }
77}