ui/components/notification/
toast_stack.rs1use crate::AnnouncementToast;
2use crate::prelude::*;
3use gpui::AnyElement;
4use smallvec::SmallVec;
5
6pub const TOAST_STACK_MAX_VISIBLE: usize = 3;
8
9#[derive(IntoElement, RegisterComponent)]
23pub struct ToastStack {
24 children: SmallVec<[AnyElement; 4]>,
25 max_visible: usize,
26}
27
28impl ToastStack {
29 pub fn new() -> Self {
30 Self {
31 children: SmallVec::new(),
32 max_visible: TOAST_STACK_MAX_VISIBLE,
33 }
34 }
35
36 pub fn max_visible(mut self, max: usize) -> Self {
38 self.max_visible = max.max(1);
39 self
40 }
41}
42
43impl Default for ToastStack {
44 fn default() -> Self {
45 Self::new()
46 }
47}
48
49impl ParentElement for ToastStack {
50 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
51 self.children.extend(elements)
52 }
53}
54
55impl RenderOnce for ToastStack {
56 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
57 let visible = self.children.into_iter().take(self.max_visible);
58
59 div().absolute().bottom_0().right_0().p_4().child(
60 v_flex()
61 .id("toast-stack")
62 .gap(DynamicSpacing::Base12.rems(cx))
63 .items_end()
64 .children(visible),
65 )
66 }
67}
68
69impl Component for ToastStack {
70 fn scope() -> ComponentScope {
71 ComponentScope::Notification
72 }
73
74 fn description() -> Option<&'static str> {
75 Some(
76 "Stacks AnnouncementToast instances bottom-right, capping visible count; auto-dismiss and list ownership stay with the caller.",
77 )
78 }
79
80 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
81 Some(
82 example_group(vec![single_example(
83 "Basic",
84 div()
85 .relative()
86 .w(px(480.))
87 .h(px(320.))
88 .overflow_hidden()
89 .child(
90 ToastStack::new()
91 .child(
92 div().w_80().child(
93 AnnouncementToast::new()
94 .severity(Severity::Success)
95 .heading("Saved")
96 .description("Your changes were saved."),
97 ),
98 )
99 .child(
100 div().w_80().child(
101 AnnouncementToast::new()
102 .severity(Severity::Info)
103 .heading("Sync complete")
104 .description("All projects are up to date."),
105 ),
106 ),
107 )
108 .into_any_element(),
109 )])
110 .into_any_element(),
111 )
112 }
113}