modal.rs

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