Aspirational examples for app developer contract.
This commit is contained in:
112
aspirational_examples/07_children_and_slots.rs
Normal file
112
aspirational_examples/07_children_and_slots.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
//! Aspirational RUIN app API for typed children, slots, and builder finalization.
|
||||
//!
|
||||
//! Intentionally non-compiling; this is a design sketch.
|
||||
|
||||
use ruin::prelude::*;
|
||||
|
||||
#[ruin_runtime::async_main]
|
||||
async fn main() -> ruin::Result<()> {
|
||||
App::new()
|
||||
.window(Window::new().title("RUIN Children Contracts").size(1100.0, 760.0))
|
||||
.mount::<ChildrenContractsExample>()
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn ChildrenContractsExample() -> impl View {
|
||||
let projects = projects();
|
||||
|
||||
view! {
|
||||
column(fill = true, gap = 20, padding = 24) {
|
||||
text(role = TextRole::Heading(1), size = 30, weight = FontWeight::Semibold) {
|
||||
"Typed children and slots"
|
||||
}
|
||||
|
||||
text(color = colors::muted()) {
|
||||
"This sketch focuses on declaration-side child contracts. The `view!` syntax stays \
|
||||
uniform for all components, while the generated builder enforces props first and \
|
||||
`children` as the finalizing step."
|
||||
}
|
||||
|
||||
SplitLayout(sidebar = view! {
|
||||
block(gap = 12, width = 280) {
|
||||
text(role = TextRole::Heading(2), size = 22, weight = FontWeight::Semibold) {
|
||||
"Filters"
|
||||
}
|
||||
FilterChip(selected = true) { "All projects" }
|
||||
FilterChip(selected = false) { "Recent" }
|
||||
}
|
||||
}) {
|
||||
column(gap = 12) {
|
||||
text(role = TextRole::Heading(2), size = 22, weight = FontWeight::Semibold) {
|
||||
"Projects"
|
||||
}
|
||||
|
||||
ForEach(items = projects, key = |project| project.id) { |project|
|
||||
ProjectRow(project = project.clone()) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dialog(
|
||||
open = true,
|
||||
title = view! {
|
||||
text(role = TextRole::Heading(2), size = 22, weight = FontWeight::Semibold) {
|
||||
"Dialog with custom title and actions"
|
||||
}
|
||||
},
|
||||
actions = view! {
|
||||
button(kind = ButtonKind::Secondary) { "Cancel" }
|
||||
button(kind = ButtonKind::Primary) { "Delete" }
|
||||
},
|
||||
) {
|
||||
text(color = colors::muted()) {
|
||||
"A dialog can declare exactly one main child body plus separately typed \
|
||||
title/actions slots."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn FilterChip(children: impl InlineChildren, selected: bool) -> impl View {
|
||||
let background = if selected {
|
||||
colors::accent()
|
||||
} else {
|
||||
colors::muted().with_alpha(0.12)
|
||||
};
|
||||
|
||||
view! {
|
||||
block(
|
||||
padding = (8, 16),
|
||||
background = background,
|
||||
corner_radius = 1000,
|
||||
) {
|
||||
children
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn ForEach<T, C>(
|
||||
items: impl IntoIterator<Item = T>,
|
||||
key: impl Fn(&T) -> u64,
|
||||
children: impl Fn(T) -> C,
|
||||
) -> impl View
|
||||
where
|
||||
C: Children,
|
||||
{
|
||||
todo!("The framework would lower this into a keyed mapper primitive or composite")
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Project {
|
||||
id: u64,
|
||||
name: String,
|
||||
}
|
||||
|
||||
fn projects() -> Vec<Project> {
|
||||
Vec::new()
|
||||
}
|
||||
Reference in New Issue
Block a user