gpui_component/
collapsible.rs1use gpui::{
2 AnyElement, App, IntoElement, ParentElement, RenderOnce, StyleRefinement, Styled, Window,
3};
4
5use crate::{v_flex, StyledExt};
6
7enum CollapsibleChild {
8 Element(AnyElement),
9 Content(AnyElement),
10}
11
12impl CollapsibleChild {
13 fn is_content(&self) -> bool {
14 matches!(self, CollapsibleChild::Content(_))
15 }
16}
17
18#[derive(IntoElement)]
20pub struct Collapsible {
21 style: StyleRefinement,
22 children: Vec<CollapsibleChild>,
23 open: bool,
24}
25
26impl Collapsible {
27 pub fn new() -> Self {
29 Self {
30 style: StyleRefinement::default(),
31 open: false,
32 children: vec![],
33 }
34 }
35
36 pub fn open(mut self, open: bool) -> Self {
38 self.open = open;
39 self
40 }
41
42 pub fn content(mut self, content: impl IntoElement) -> Self {
46 self.children
47 .push(CollapsibleChild::Content(content.into_any_element()));
48 self
49 }
50}
51
52impl Styled for Collapsible {
53 fn style(&mut self) -> &mut StyleRefinement {
54 &mut self.style
55 }
56}
57
58impl ParentElement for Collapsible {
59 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
60 self.children
61 .extend(elements.into_iter().map(|el| CollapsibleChild::Element(el)));
62 }
63}
64
65impl RenderOnce for Collapsible {
66 fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
67 v_flex()
68 .refine_style(&self.style)
69 .children(self.children.into_iter().filter_map(|child| {
70 if child.is_content() && !self.open {
71 None
72 } else {
73 match child {
74 CollapsibleChild::Element(el) => Some(el),
75 CollapsibleChild::Content(el) => Some(el),
76 }
77 }
78 }))
79 }
80}