Skip to main content

teksilo_core/styles/
toast_style.rs

1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4//! Tier-3 style protocol for `Toast`. See `docs/styling-system.md`.
5//!
6//! Themes the floating toast surface — the per-severity card the
7//! `ToastHost` stacks at a viewport corner. The `Toast` widget keeps
8//! its accessibility node (`Role::Alert` for Warning/Error,
9//! `Role::Status` for Info/Success, plus the matching `Live` setting);
10//! `ToastStyle` only owns the surface chrome.
11//!
12//! `ToastStyleConfig` exposes both severity AND priority so the recipe
13//! can give Urgent/High toasts a slightly heavier shadow or a more
14//! emphatic border without changing the severity tint. Pre-built child
15//! ids (`content`, `leading_glyph`, `trailing_close`) follow the same
16//! pattern as `BannerStyleConfig` — the widget assembles the functional
17//! subtrees, the recipe arranges them.
18
19use std::rc::Rc;
20
21use serde::{Deserialize, Serialize};
22
23use crate::build_context::BuildContext;
24use crate::styles::BannerSeverity;
25use crate::widget_id::WidgetId;
26
27/// Queue / assertiveness level — shared with the public `Toast` builder
28/// API. Lives here in teksilo-core so the style trait can take it in its
29/// config without depending on teksilo-widgets.
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
31pub enum ToastPriority {
32    /// Queues if `max_visible` reached; admits in order. Default.
33    #[default]
34    Normal,
35    /// Shown immediately; bumps the oldest Normal entry if needed.
36    /// Doesn't interrupt screen-reader speech.
37    High,
38    /// Shown immediately; forces `Live::Assertive` regardless of severity.
39    Urgent,
40}
41
42#[derive(Clone, Debug)]
43pub struct ToastStyleConfig {
44    /// Severity hint — drives the recipe's surface tint (same mapping
45    /// as `BannerSeverity::surface()`).
46    pub severity: BannerSeverity,
47    /// Priority hint — recipes can use this to differentiate Urgent
48    /// toasts (e.g., heavier shadow). Most recipes ignore it.
49    pub priority: ToastPriority,
50    /// Pre-built body subtree (title + body + optional action row +
51    /// optional progress bar). The recipe arranges it next to the
52    /// leading glyph.
53    pub content: WidgetId,
54    /// Pre-built `SeverityGlyph` (or app-supplied custom leading
55    /// widget). The recipe places it at the leading edge.
56    pub leading_glyph: WidgetId,
57    /// Optional pre-built close `IconButton`. `None` when the toast
58    /// was constructed with `.show_close_button(false)`.
59    pub trailing_close: Option<WidgetId>,
60}
61
62pub trait ToastStyle: 'static {
63    fn make_body(&self, cfg: &ToastStyleConfig, ctx: &mut BuildContext) -> WidgetId;
64}
65
66pub type SharedToastStyle = Rc<dyn ToastStyle>;