toast.rs

 1use crate::prelude::*;
 2use gpui::{prelude::*, AnyElement};
 3use smallvec::SmallVec;
 4
 5#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
 6pub enum ToastOrigin {
 7    #[default]
 8    Bottom,
 9    BottomRight,
10}
11
12/// Don't use toast directly:
13///
14/// - For messages with a required action, use a `NotificationToast`.
15/// - For messages that convey information, use a `StatusToast`.
16///
17/// A toast is a small, temporary window that appears to show a message to the user
18/// or indicate a required action.
19///
20/// Toasts should not persist on the screen for more than a few seconds unless
21/// they are actively showing the a process in progress.
22///
23/// Only one toast may be visible at a time.
24#[derive(Component)]
25pub struct Toast<V: 'static> {
26    origin: ToastOrigin,
27    children: SmallVec<[AnyElement<V>; 2]>,
28}
29
30impl<V: 'static> Toast<V> {
31    pub fn new(origin: ToastOrigin) -> Self {
32        Self {
33            origin,
34            children: SmallVec::new(),
35        }
36    }
37
38    fn render(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
39        let mut div = div();
40
41        if self.origin == ToastOrigin::Bottom {
42            div = div.right_1_2();
43        } else {
44            div = div.right_2();
45        }
46
47        div.z_index(5)
48            .absolute()
49            .bottom_9()
50            .flex()
51            .py_1()
52            .px_1p5()
53            .rounded_lg()
54            .shadow_md()
55            .overflow_hidden()
56            .bg(cx.theme().colors().elevated_surface_background)
57            .children(self.children)
58    }
59}
60
61impl<V: 'static> ParentComponent<V> for Toast<V> {
62    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
63        &mut self.children
64    }
65}
66
67#[cfg(feature = "stories")]
68pub use stories::*;
69
70#[cfg(feature = "stories")]
71mod stories {
72    use gpui::{Div, Render};
73
74    use crate::{Label, Story};
75
76    use super::*;
77
78    pub struct ToastStory;
79
80    impl Render for ToastStory {
81        type Element = Div<Self>;
82
83        fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
84            Story::container(cx)
85                .child(Story::title_for::<_, Toast<Self>>(cx))
86                .child(Story::label(cx, "Default"))
87                .child(Toast::new(ToastOrigin::Bottom).child(Label::new("label")))
88        }
89    }
90}