//! Aspirational RUIN app API. //! //! This file is intentionally not wired into the workspace build. It exists to illustrate the //! desired developer-facing programming model for a component-driven app framework. use ruin::prelude::*; #[ruin_runtime::async_main] async fn main() -> ruin::Result<()> { App::new() .window(Window::new().title("RUIN Counter").size(960.0, 640.0)) .mount::() .run() .await } #[component] fn CounterApp() -> impl View { let count = use_signal(|| 0); let doubled = use_memo(move || count.get() * 2); use_window_title(move || format!("RUIN Counter ({})", count.get())); use_effect(move || tracing::info!(count = count.get(), "counter changed")); view! { column(gap = 16, padding = 24) { text( role = TextRole::Heading(1), size = 32, weight = FontWeight::Semibold, ) { "RUIN counter" } text(color = colors::muted()) { "The obvious primitives here should be layout, text, and input surfaces. Higher-level \ ideas like cards or panels should probably be composites layered on top of `block`." } row(gap = 8) { button(on_press = move |_| count.update(|value| *value -= 1)) { "-1" } button(on_press = move |_| count.set(0)) { "Reset" } button(on_press = move |_| count.update(|value| *value += 1)) { "+1" } } block( padding = 16, gap = 8, background = surfaces::raised(), border_radius = 12, ) { text(size = 18) { "count = "; count } text(color = colors::muted()) { "double = "; doubled } } } } }