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