Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-app/examples/starter_app.rs

//! **The facett-app starter** — a complete, minimal app you can copy.
//!
//! `cargo run -p facett-app --example starter_app`
//!
//! Shows the whole pattern end-to-end: define your own `Facet`, build a
//! `NavModel`, mount panes in an `AppShell`, and run it full-window. Native +
//! wasm (canvas) from one code path. This file IS the `create-facett-app` template
//! until a cargo-generate scaffold lands.

use eframe::egui;
use facett_app::{AppShell, NavItem, NavModel, Stepper, Toasts, Level};
use facett_core::{Facet, FacetCaps};

// 1) Your own component — anything implementing `Facet` can be a page.
struct CounterPage {
    title: String,
    stepper: Stepper,
    toasts: Toasts,
}
impl CounterPage {
    fn new() -> Self {
        Self { title: "counter".into(), stepper: Stepper::new(0).range(0, 20), toasts: Toasts::new() }
    }
}
impl Facet for CounterPage {
    fn title(&self) -> &str {
        &self.title
    }
    fn ui(&mut self, ui: &mut egui::Ui) {
        ui.heading("Counter");
        ui.label("A page is just a Facet. This one owns a Stepper + a toast queue.");
        if let Some(v) = self.stepper.show(ui) {
            self.toasts.push(if v == 20 { Level::Warn } else { Level::Info }, format!("count = {v}"));
        }
        self.toasts.show(ui);
    }
    fn state_json(&self) -> serde_json::Value {
        serde_json::json!({ "stepper": self.stepper.state_json() })
    }
    fn caps(&self) -> FacetCaps {
        FacetCaps::NONE.themeable()
    }
}

// 2) The app shell wraps your pages with nav + chrome.
struct App {
    shell: AppShell,
}
impl Default for App {
    fn default() -> Self {
        let model = NavModel::new([
            NavItem::new("home", "Home").icon("🏠"),
            NavItem::new("counter", "Counter").icon("🔢"),
            NavItem::new("about", "About").icon("ℹ"),
        ]);
        let shell = AppShell::new("My facett app", model)
            .with_body("home", "Welcome! Edit examples/starter_app.rs to make it yours.")
            .with_pane("counter", Box::new(CounterPage::new()))
            .with_body("about", "Built with facett-app — an egui app framework. Native + wasm from one codebase.")
            .with_status("ready");
        Self { shell }
    }
}
impl eframe::App for App {
    fn ui(&mut self, root: &mut egui::Ui, _frame: &mut eframe::Frame) {
        // 3) The shell is the whole window.
        egui::CentralPanel::default().show(root, |ui| self.shell.ui(ui));
    }
}

fn main() -> eframe::Result {
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size(egui::Vec2::new(820.0, 600.0)),
        ..Default::default()
    };
    eframe::run_native("facett-app · starter", options, Box::new(|_cc| Ok(Box::<App>::default())))
}