use gpui3::AnyElement; use smallvec::SmallVec; use crate::prelude::*; #[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] pub enum ToastOrigin { #[default] Bottom, BottomRight, } /// A toast is a small, temporary window that appears to show a message to the user /// or indicate a required action. /// /// Toasts should not persist on the screen for more than a few seconds unless /// they are actively showing the a process in progress. /// /// Only one toast may be visible at a time. #[derive(Element)] pub struct Toast { origin: ToastOrigin, children: SmallVec<[AnyElement; 2]>, } impl Toast { pub fn new(origin: ToastOrigin) -> Self { Self { origin, children: SmallVec::new(), } } fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { let color = ThemeColor::new(cx); let mut div = div(); if self.origin == ToastOrigin::Bottom { div = div.right_1_2(); } else { div = div.right_4(); } div.z_index(5) .absolute() .bottom_4() .flex() .py_2() .px_1p5() .min_w_64() .rounded_md() .fill(color.elevated_surface) .max_w_96() .children(self.children.drain(..)) } } impl ParentElement for Toast { type State = S; fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children } } #[cfg(feature = "stories")] pub use stories::*; #[cfg(feature = "stories")] mod stories { use std::marker::PhantomData; use crate::{Label, Story}; use super::*; #[derive(Element)] pub struct ToastStory { state_type: PhantomData, } impl ToastStory { pub fn new() -> Self { Self { state_type: PhantomData, } } fn render( &mut self, _view: &mut S, cx: &mut ViewContext, ) -> impl Element { Story::container(cx) .child(Story::title_for::<_, Toast>(cx)) .child(Story::label(cx, "Default")) .child(Toast::new(ToastOrigin::Bottom).child(Label::new("label"))) } } }