toast.rs

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