use crate::AnnouncementToast;
use crate::prelude::*;
use gpui::AnyElement;
use smallvec::SmallVec;
pub const TOAST_STACK_MAX_VISIBLE: usize = 3;
#[derive(IntoElement, RegisterComponent)]
pub struct ToastStack {
children: SmallVec<[AnyElement; 4]>,
max_visible: usize,
}
impl ToastStack {
pub fn new() -> Self {
Self {
children: SmallVec::new(),
max_visible: TOAST_STACK_MAX_VISIBLE,
}
}
pub fn max_visible(mut self, max: usize) -> Self {
self.max_visible = max.max(1);
self
}
}
impl Default for ToastStack {
fn default() -> Self {
Self::new()
}
}
impl ParentElement for ToastStack {
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
self.children.extend(elements)
}
}
impl RenderOnce for ToastStack {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let visible = self.children.into_iter().take(self.max_visible);
div().absolute().bottom_0().right_0().p_4().child(
v_flex()
.id("toast-stack")
.gap(DynamicSpacing::Base12.rems(cx))
.items_end()
.children(visible),
)
}
}
impl Component for ToastStack {
fn scope() -> ComponentScope {
ComponentScope::Notification
}
fn description() -> Option<&'static str> {
Some(
"Stacks AnnouncementToast instances bottom-right, capping visible count; auto-dismiss and list ownership stay with the caller.",
)
}
fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
Some(
example_group(vec![single_example(
"Basic",
div()
.relative()
.w(px(480.))
.h(px(320.))
.overflow_hidden()
.child(
ToastStack::new()
.child(
div().w_80().child(
AnnouncementToast::new()
.severity(Severity::Success)
.heading("Saved")
.description("Your changes were saved."),
),
)
.child(
div().w_80().child(
AnnouncementToast::new()
.severity(Severity::Info)
.heading("Sync complete")
.description("All projects are up to date."),
),
),
)
.into_any_element(),
)])
.into_any_element(),
)
}
}