Toast for Slint
KitToast · Slint Kit 0.3.1
Identified transient notification with optional action and dismissal.

Try the component
Download the complete project, extract it and run cargo run --locked in its folder. Rust 1.92+; Slint Kit 0.3.0 from crates.io. You can also copy the four files below.
Show an archive notice, Undo its action, or dismiss it. This example keeps notices until an explicit action.
ui/app.slint
export { KitFormValidation, HtmlInputKind, NumberInputFormat, KitInputConstraints, KitValidationResult, KitValidityState } from "@kit/kit.slint";
// SPDX-License-Identifier: GPL-3.0-or-later
import { KitToast, KitButton, ToastEntry, ToastInteraction, AlertSeverity, KitTheme, KitThemes } from "@kit/kit.slint";
export component App inherits Window {
title: "KitToast example";
preferred-width: 520px;
preferred-height: 420px;
max-width: 100000px;
max-height: 100000px;
background: root.theme.canvas;
in-out property <KitTheme> theme: KitThemes.light;
in property <[ToastEntry]> entries;
in property <string> result: "Project archived";
callback undo(int);
callback dismiss-toast(int);
callback interaction(int, ToastInteraction, bool);
callback add();
VerticalLayout {
padding: 24px;
spacing: 16px;
alignment: start;
KitButton { theme: root.theme; text: "Show archive notice"; activated => { root.add(); } }
if root.entries.length > 0: control := KitToast { theme: root.theme; entry: root.entries[0]; action(token) => { root.undo(token); } dismiss(token) => { root.dismiss-toast(token); } interaction(token, source, engaged) => { root.interaction(token, source, engaged); } }
result := Text { text: root.result; color: root.theme.text-primary; }
}
}
src/main.rs
// SPDX-License-Identifier: GPL-3.0-or-later
use web_time::Instant;
use slint::{ComponentHandle, ModelRc, VecModel};
use slint_kit::{ToastQueue, ToastLifetime, ToastPause};
use std::{cell::RefCell, rc::Rc, num::NonZeroUsize};
mod ui { slint::include_modules!(); }
fn publish(app: &ui::App, queue: &ToastQueue<()>) {
let entries = queue.entries().map(|entry| ui::ToastEntry { token: i32::try_from(entry.id.get()).expect("view token capacity"), title: "Project archived".into(), message: "Your project can be restored.".into(), action_label: "Undo".into(), severity: ui::AlertSeverity::Success, dismissible: true }).collect::<Vec<_>>();
app.set_entries(ModelRc::new(VecModel::from(entries)));
}
fn main() -> Result<(), slint::PlatformError> {
let app = ui::App::new()?;
slint_kit::init_form_validation!(ui, app);
let epoch = Instant::now();
let queue = Rc::new(RefCell::new(ToastQueue::new(NonZeroUsize::new(1).unwrap())));
queue.borrow_mut().push((), ToastLifetime::Persistent, epoch.elapsed()).expect("toast identity");
publish(&app, &queue.borrow());
let state = queue.clone(); let weak = app.as_weak();
app.on_add(move || { state.borrow_mut().push((), ToastLifetime::Persistent, epoch.elapsed()).expect("toast identity"); if let Some(app) = weak.upgrade() { publish(&app, &state.borrow()); app.set_result("Project archived".into()); } });
let state = queue.clone(); let weak = app.as_weak();
app.on_undo(move |token| {
let id = state.borrow().entries().find(|entry| i32::try_from(entry.id.get()).ok() == Some(token)).map(|entry| entry.id);
if let Some(id) = id { state.borrow_mut().remove(id); if let Some(app) = weak.upgrade() { publish(&app, &state.borrow()); app.set_result("Archive undone".into()); } }
});
let state = queue.clone(); let weak = app.as_weak();
app.on_dismiss_toast(move |token| {
let id = state.borrow().entries().find(|entry| i32::try_from(entry.id.get()).ok() == Some(token)).map(|entry| entry.id);
if let Some(id) = id { state.borrow_mut().remove(id); if let Some(app) = weak.upgrade() { publish(&app, &state.borrow()); app.set_result("Toast dismissed".into()); } }
});
app.on_interaction(move |token, source, engaged| {
let id = queue.borrow().entries().find(|entry| i32::try_from(entry.id.get()).ok() == Some(token)).map(|entry| entry.id);
if let Some(id) = id { queue.borrow_mut().set_paused(id, match source { ui::ToastInteraction::Pointer => ToastPause::Pointer, ui::ToastInteraction::Focus => ToastPause::Focus }, engaged, epoch.elapsed()); }
});
app.run()
}
Cargo.toml and build.rs
Cargo.toml
[package]
name = "slint-kit-toast-example"
version = "0.1.0"
edition = "2024"
rust-version = "1.92"
license = "GPL-3.0-or-later"
publish = false
[dependencies]
web-time = "=1.1.0"
slint-kit = "=0.3.0"
slint = { version = "=1.18.1", default-features = false, features = ["std", "compat-1-18", "backend-winit", "renderer-skia", "accessibility"] }
[build-dependencies]
slint-kit-build = "=0.3.0"
[workspace]
build.rs
fn main() { slint_kit_build::compile("ui/app.slint").expect("compile component example"); }
Files: Cargo.toml · build.rs · ui/app.slint · src/main.rs
Supply entry: ToastEntry and handle action(token) and dismiss(token) in the owning queue. Connect interaction(token, ToastInteraction, bool) to Rust lifetime pauses.
ToastInteraction.pointer and .focus are separate pause sources. The view adds no timer; the controller preserves remaining lifetime and stable identities.
Visual composition
The file below produces the screenshot. For controller-driven components, it shows the displayed state without supplying the Rust wiring. Create a project.
Show the screenshot source

// SPDX-License-Identifier: GPL-3.0-or-later
import { AlertSeverity, KitTheme, KitThemes, KitToast } from "@kit/kit.slint";
export component Example inherits Window {
title: "KitToast example";
preferred-width: 480px;
preferred-height: 260px;
max-width: 100000px;
max-height: 100000px;
background: root.theme.canvas;
in-out property <KitTheme> theme: KitThemes.light;
in-out property <string> status;
VerticalLayout {
padding: 24px; spacing: 16px; alignment: start;
Text { text: "Toast"; color: root.theme.text-primary; font-size: 20px * root.theme.text-scale; font-weight: 600; }
KitToast { theme: root.theme; entry: { token: 11, title: "Project archived", message: "Your notes are safely stored.", action-label: "Undo", severity: AlertSeverity.success, dismissible: true }; action(token) => { root.status = "Undo requested"; } }
if root.status != "": Text { text: root.status; color: root.theme.text-secondary; font-size: 12px * root.theme.text-scale; wrap: word-wrap; }
}
}
Public API
Inherits Rectangle.
Properties
| Name | Type | Direction |
|---|---|---|
theme |
KitTheme |
in |
entry |
ToastEntry |
in |
Types and variants
| Type | Declaration |
|---|---|
enum AlertSeverity |
information, success, warning, error |
struct ToastEntry |
token: int, title: string, message: string, action-label: string, severity: AlertSeverity, dismissible: bool |
enum ToastInteraction |
pointer, focus |
Callbacks
action(int)dismiss(int)interaction(int,ToastInteraction,bool)