modal.rs

 1use gpui::{AnyElement, Div, RenderOnce, Stateful};
 2use smallvec::SmallVec;
 3
 4use crate::{h_stack, prelude::*, v_stack, Button, Icon, IconButton, Label};
 5
 6#[derive(RenderOnce)]
 7pub struct Modal<V: 'static> {
 8    id: ElementId,
 9    title: Option<SharedString>,
10    primary_action: Option<Button<V>>,
11    secondary_action: Option<Button<V>>,
12    children: SmallVec<[AnyElement<V>; 2]>,
13}
14
15impl<V: 'static> Component<V> for Modal<V> {
16    type Rendered = Stateful<V, Div<V>>;
17
18    fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> Self::Rendered {
19        let _view: &mut V = view;
20        v_stack()
21            .id(self.id.clone())
22            .w_96()
23            // .rounded_xl()
24            .bg(cx.theme().colors().background)
25            .border()
26            .border_color(cx.theme().colors().border)
27            .shadow_2xl()
28            .child(
29                h_stack()
30                    .justify_between()
31                    .p_1()
32                    .border_b()
33                    .border_color(cx.theme().colors().border)
34                    .child(div().children(self.title.clone().map(|t| Label::new(t))))
35                    .child(IconButton::new("close", Icon::Close)),
36            )
37            .child(v_stack().p_1().children(self.children))
38            .when(
39                self.primary_action.is_some() || self.secondary_action.is_some(),
40                |this| {
41                    this.child(
42                        h_stack()
43                            .border_t()
44                            .border_color(cx.theme().colors().border)
45                            .p_1()
46                            .justify_end()
47                            .children(self.secondary_action)
48                            .children(self.primary_action),
49                    )
50                },
51            )
52    }
53}
54
55impl<V: 'static> Modal<V> {
56    pub fn new(id: impl Into<ElementId>) -> Self {
57        Self {
58            id: id.into(),
59            title: None,
60            primary_action: None,
61            secondary_action: None,
62            children: SmallVec::new(),
63        }
64    }
65
66    pub fn title(mut self, title: impl Into<SharedString>) -> Self {
67        self.title = Some(title.into());
68        self
69    }
70
71    pub fn primary_action(mut self, action: Button<V>) -> Self {
72        self.primary_action = Some(action);
73        self
74    }
75
76    pub fn secondary_action(mut self, action: Button<V>) -> Self {
77        self.secondary_action = Some(action);
78        self
79    }
80}
81
82impl<V: 'static> ParentElement<V> for Modal<V> {
83    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
84        &mut self.children
85    }
86}