facett-demo/src/overlay_demo.rs
//! **`overlay` demo tab** — exercises the facett-app overlay/feedback system
//! (Fas 3): a [`Modal`] dialog + a [`Toasts`] notification queue. Buttons open the
//! dialog and push levelled toasts; confirming the dialog fires a success toast.
use facett_app::{Level, Modal, Popover, Toasts};
use facett_core::{Facet, FacetCaps};
pub struct OverlayDemo {
title: String,
modal: Modal,
toasts: Toasts,
popover: Popover,
last_action: Option<String>,
}
impl OverlayDemo {
pub fn new() -> Self {
Self {
title: "overlay".into(),
modal: Modal::new("demo_modal", "Delete this item?").body("This action cannot be undone.").confirm_cancel(),
toasts: Toasts::new(),
popover: Popover::new("demo_popover"),
last_action: None,
}
}
/// Seed some observable state (for the headless coverage matrix): open the
/// dialog + queue a couple of toasts.
pub fn seed_for_demo(&mut self) {
self.modal.open();
self.toasts.push(Level::Info, "Welcome.");
self.toasts.push_sticky(Level::Warn, "Disk almost full.");
}
}
impl Default for OverlayDemo {
fn default() -> Self {
Self::new()
}
}
impl Facet for OverlayDemo {
fn title(&self) -> &str {
&self.title
}
fn ui(&mut self, ui: &mut egui::Ui) {
ui.horizontal_wrapped(|ui| {
if ui.button("Open dialog").clicked() {
self.modal.open();
}
if ui.button("ℹ Info").clicked() {
self.toasts.push(Level::Info, "Heads up.");
}
if ui.button("✓ Success").clicked() {
self.toasts.push(Level::Success, "Saved.");
}
if ui.button("⚠ Warn").clicked() {
self.toasts.push(Level::Warn, "Careful now.");
}
if ui.button("✖ Error").clicked() {
self.toasts.push_sticky(Level::Error, "Something failed (sticky).");
}
let pop = ui.button("Popover ▾");
if pop.clicked() {
self.popover.toggle();
}
self.popover.show(ui, &pop, |ui| {
ui.strong("Popover");
ui.label("An anchored floating panel (Fas 3 extra). Esc closes.");
});
});
ui.separator();
ui.label("Modal generalises the command-palette overlay (scrim + Esc); Toasts generalise the deck toast into a levelled queue. Both headless + observable (state_json).");
if let Some(a) = self.last_action.as_deref() {
ui.add_space(4.0);
ui.weak(format!("last dialog action: {a}"));
}
// Overlays draw on top of everything.
if let Some(action) = self.modal.show(ui) {
self.last_action = Some(action.clone());
match action.as_str() {
"ok" => {
self.toasts.push(Level::Success, "Confirmed — item deleted.");
}
"cancel" | "dismiss" => {
self.toasts.push(Level::Info, "Cancelled.");
}
_ => {}
}
}
self.toasts.show(ui);
}
fn state_json(&self) -> serde_json::Value {
serde_json::json!({
"modal": self.modal.state_json(),
"toasts": self.toasts.state_json(),
"popover": self.popover.state_json(),
"last_action": self.last_action,
})
}
fn caps(&self) -> FacetCaps {
FacetCaps::NONE.themeable()
}
}