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 {
18 Self {
19 base: div().gap_2().flex_col(),
20 label: label.into(),
21 collapsed: false,
22 children: Vec::new(),
23 }
24 }
25
26 pub fn child(mut self, child: E) -> Self {
27 self.children.push(child);
28 self
29 }
30
31 pub fn children(mut self, children: impl IntoIterator<Item = E>) -> Self {
32 self.children.extend(children);
33 self
34 }
35}
36impl<E: Collapsible + IntoElement> Collapsible for SidebarGroup<E> {
37 fn is_collapsed(&self) -> bool {
38 self.collapsed
39 }
40
41 fn collapsed(mut self, collapsed: bool) -> Self {
42 self.collapsed = collapsed;
43 self
44 }
45}
46impl<E: Collapsible + IntoElement> RenderOnce for SidebarGroup<E> {
47 fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
48 v_flex()
49 .relative()
50 .p_2()
51 .when(!self.collapsed, |this| {
52 this.child(
53 div()
54 .flex_shrink_0()
55 .px_2()
56 .rounded(cx.theme().radius)
57 .text_xs()
58 .text_color(cx.theme().sidebar_foreground.opacity(0.7))
59 .h_8()
60 .child(self.label),
61 )
62 })
63 .child(
64 self.base.children(
65 self.children
66 .into_iter()
67 .map(|child| child.collapsed(self.collapsed)),
68 ),
69 )
70 }
71}