rgpui_component/sidebar/
group.rs1use crate::{ActiveTheme, Collapsible, h_flex, sidebar::SidebarItem, v_flex};
2use rgpui::{
3 App, ElementId, IntoElement, ParentElement, SharedString, Styled as _, Window, div,
4 prelude::FluentBuilder as _,
5};
6
7#[derive(Clone)]
9pub struct SidebarGroup<E: SidebarItem + 'static> {
10 label: SharedString,
11 collapsed: bool,
12 children: Vec<E>,
13}
14
15impl<E: SidebarItem> SidebarGroup<E> {
16 pub fn new(label: impl Into<SharedString>) -> Self {
18 Self {
19 label: label.into(),
20 collapsed: false,
21 children: Vec::new(),
22 }
23 }
24
25 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 {
35 self.children.extend(children);
36 self
37 }
38}
39
40impl<E: SidebarItem> Collapsible for SidebarGroup<E> {
41 fn is_collapsed(&self) -> bool {
42 self.collapsed
43 }
44
45 fn collapsed(mut self, collapsed: bool) -> Self {
46 self.collapsed = collapsed;
47 self
48 }
49}
50
51impl<E: SidebarItem> SidebarItem for SidebarGroup<E> {
52 fn render(
53 self,
54 id: impl Into<ElementId>,
55 window: &mut Window,
56 cx: &mut App,
57 ) -> impl IntoElement {
58 let id = id.into();
59
60 v_flex()
61 .relative()
62 .when(!self.collapsed, |this| {
63 this.child(
64 h_flex()
65 .flex_shrink_0()
66 .px_2()
67 .rounded(cx.theme().radius)
68 .text_xs()
69 .text_color(cx.theme().sidebar_foreground.opacity(0.7))
70 .h_8()
71 .child(self.label),
72 )
73 })
74 .child(
75 div()
76 .gap_2()
77 .flex_col()
78 .children(self.children.into_iter().enumerate().map(|(ix, child)| {
79 child
80 .collapsed(self.collapsed)
81 .render(format!("{}-{}", id, ix), window, cx)
82 .into_any_element()
83 })),
84 )
85 }
86}