notification: Add built-in dismiss button in the Status Toast component (#33278)

There may be cases where we're needing to pass a button just so it is
dismissible, so I figured this out help! It also helps when you want to
have two buttons, one to perform an action and another to dismiss and
cancel.

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2025-06-23 19:55:21 -03:00 committed by GitHub
parent 36eebb7ba8
commit 32df9256c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -39,6 +39,7 @@ pub struct StatusToast {
icon: Option<ToastIcon>, icon: Option<ToastIcon>,
text: SharedString, text: SharedString,
action: Option<ToastAction>, action: Option<ToastAction>,
show_dismiss: bool,
this_handle: Entity<Self>, this_handle: Entity<Self>,
focus_handle: FocusHandle, focus_handle: FocusHandle,
} }
@ -57,6 +58,7 @@ impl StatusToast {
text: text.into(), text: text.into(),
icon: None, icon: None,
action: None, action: None,
show_dismiss: false,
this_handle: cx.entity(), this_handle: cx.entity(),
focus_handle, focus_handle,
}, },
@ -87,20 +89,33 @@ impl StatusToast {
)); ));
self self
} }
pub fn dismiss_button(mut self, show: bool) -> Self {
self.show_dismiss = show;
self
}
} }
impl Render for StatusToast { impl Render for StatusToast {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let has_action_or_dismiss = self.action.is_some() || self.show_dismiss;
h_flex() h_flex()
.id("status-toast") .id("status-toast")
.elevation_3(cx) .elevation_3(cx)
.gap_2() .gap_2()
.py_1p5() .py_1p5()
.px_2p5() .pl_2p5()
.map(|this| {
if has_action_or_dismiss {
this.pr_1p5()
} else {
this.pr_2p5()
}
})
.flex_none() .flex_none()
.bg(cx.theme().colors().surface_background) .bg(cx.theme().colors().surface_background)
.shadow_lg() .shadow_lg()
.items_center()
.when_some(self.icon.as_ref(), |this, icon| { .when_some(self.icon.as_ref(), |this, icon| {
this.child(Icon::new(icon.icon).color(icon.color)) this.child(Icon::new(icon.icon).color(icon.color))
}) })
@ -118,6 +133,20 @@ impl Render for StatusToast {
}), }),
) )
}) })
.when(self.show_dismiss, |this| {
let handle = self.this_handle.clone();
this.child(
IconButton::new("dismiss", IconName::Close)
.icon_size(IconSize::XSmall)
.icon_color(Color::Muted)
.tooltip(Tooltip::text("Dismiss"))
.on_click(move |_click_event, _window, cx| {
handle.update(cx, |_, cx| {
cx.emit(DismissEvent);
});
}),
)
})
} }
} }
@ -147,6 +176,9 @@ impl Component for StatusToast {
this.action("Restart", |_, _| {}) this.action("Restart", |_, _| {})
}); });
let dismiss_button_example =
StatusToast::new("Dismiss Button", cx, |this, _| this.dismiss_button(true));
let icon_example = StatusToast::new( let icon_example = StatusToast::new(
"Nathan Sobo accepted your contact request", "Nathan Sobo accepted your contact request",
cx, cx,
@ -193,6 +225,10 @@ impl Component for StatusToast {
div().child(action_example).into_any_element(), div().child(action_example).into_any_element(),
), ),
single_example("Icon", div().child(icon_example).into_any_element()), single_example("Icon", div().child(icon_example).into_any_element()),
single_example(
"Dismiss Button",
div().child(dismiss_button_example).into_any_element(),
),
], ],
), ),
example_group_with_title( example_group_with_title(