1use std::sync::Arc;
2
3use gpui::ClickEvent;
4
5use crate::{prelude::*, Color, IconButton, IconButtonShape, IconName, IconSize};
6
7#[derive(IntoElement)]
8pub struct Disclosure {
9 id: ElementId,
10 is_open: bool,
11 selected: bool,
12 on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
13}
14
15impl Disclosure {
16 pub fn new(id: impl Into<ElementId>, is_open: bool) -> Self {
17 Self {
18 id: id.into(),
19 is_open,
20 selected: false,
21 on_toggle: None,
22 }
23 }
24
25 pub fn on_toggle(
26 mut self,
27 handler: impl Into<Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>>,
28 ) -> Self {
29 self.on_toggle = handler.into();
30 self
31 }
32}
33
34impl Selectable for Disclosure {
35 fn selected(mut self, selected: bool) -> Self {
36 self.selected = selected;
37 self
38 }
39}
40
41impl Clickable for Disclosure {
42 fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
43 self.on_toggle = Some(Arc::new(handler));
44 self
45 }
46}
47
48impl RenderOnce for Disclosure {
49 fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
50 IconButton::new(
51 self.id,
52 match self.is_open {
53 true => IconName::ChevronDown,
54 false => IconName::ChevronRight,
55 },
56 )
57 .shape(IconButtonShape::Square)
58 .icon_color(Color::Muted)
59 .icon_size(IconSize::Small)
60 .selected(self.selected)
61 .when_some(self.on_toggle, move |this, on_toggle| {
62 this.on_click(move |event, cx| on_toggle(event, cx))
63 })
64 }
65}