ui/components/
alert_dialog.rs1use smallvec::SmallVec;
2
3use crate::{Modal, ModalFooter, ModalHeader, prelude::*};
4
5#[derive(IntoElement, RegisterComponent)]
10pub struct AlertDialog {
11 id: SharedString,
12 title: SharedString,
13 description: Option<SharedString>,
14 children: SmallVec<[AnyElement; 2]>,
15 action_label: SharedString,
16 cancel_label: SharedString,
17 destructive: bool,
18}
19
20impl AlertDialog {
21 pub fn new(id: impl Into<SharedString>, title: impl Into<SharedString>) -> Self {
22 Self {
23 id: id.into(),
24 title: title.into(),
25 description: None,
26 children: SmallVec::new(),
27 action_label: "Continue".into(),
28 cancel_label: "Cancel".into(),
29 destructive: false,
30 }
31 }
32
33 pub fn description(mut self, description: impl Into<SharedString>) -> Self {
34 self.description = Some(description.into());
35 self
36 }
37
38 pub fn action_label(mut self, label: impl Into<SharedString>) -> Self {
39 self.action_label = label.into();
40 self
41 }
42
43 pub fn cancel_label(mut self, label: impl Into<SharedString>) -> Self {
44 self.cancel_label = label.into();
45 self
46 }
47
48 pub fn destructive(mut self, destructive: bool) -> Self {
49 self.destructive = destructive;
50 self
51 }
52}
53
54impl ParentElement for AlertDialog {
55 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
56 self.children.extend(elements)
57 }
58}
59
60impl RenderOnce for AlertDialog {
61 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
62 let mut header = ModalHeader::new()
63 .headline(self.title)
64 .show_dismiss_button(false);
65 if let Some(description) = self.description {
66 header = header.description(description);
67 }
68
69 let action = self.action_label.clone();
70 let cancel = self.cancel_label.clone();
71 let destructive = self.destructive;
72
73 div().w(px(440.)).child(
74 Modal::new(self.id, None)
75 .header(header)
76 .children(self.children)
77 .footer(
78 ModalFooter::new().end_slot(
79 h_flex()
80 .gap_2()
81 .child(Button::new("alert-cancel", cancel.clone()).color(Color::Muted))
82 .child({
83 let btn = Button::new("alert-action", action.clone());
84 if destructive {
85 btn.danger()
86 } else {
87 btn.primary()
88 }
89 }),
90 ),
91 ),
92 )
93 }
94}
95
96impl Component for AlertDialog {
97 fn scope() -> ComponentScope {
98 ComponentScope::Overlays
99 }
100
101 fn description() -> Option<&'static str> {
102 Some("A modal alert preset with action and cancel buttons, built on Modal.")
103 }
104
105 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
106 Some(
107 v_flex()
108 .gap_6()
109 .child(
110 AlertDialog::new("alert-basic", "Are you absolutely sure?")
111 .description("This action cannot be undone.")
112 .action_label("Continue")
113 .cancel_label("Cancel"),
114 )
115 .child(
116 AlertDialog::new("alert-destructive", "Delete account?")
117 .description("This will permanently delete your account and all data.")
118 .action_label("Delete")
119 .destructive(true),
120 )
121 .into_any_element(),
122 )
123 }
124}