195 lines
7.1 KiB
Rust
195 lines
7.1 KiB
Rust
//! Visual demonstration of every supported `justify_content` mode.
|
|
//!
|
|
//! The window arranges one labeled cell per mode in a two-column grid. Each
|
|
//! cell is a flex container of the same fixed width with four
|
|
//! identically-sized children, so the only visible difference between cells is
|
|
//! how `justify_content` distributes the leftover space along the main axis.
|
|
|
|
use ruin_app::prelude::*;
|
|
|
|
const TRACK_WIDTH: f32 = 360.0;
|
|
const ITEM_SIZE: f32 = 44.0;
|
|
|
|
#[ruin_runtime::async_main]
|
|
async fn main() -> ruin_app::Result<()> {
|
|
App::new()
|
|
.window(
|
|
Window::new()
|
|
.title("RUIN justify_content")
|
|
.app_id("dev.ruin.justify-content")
|
|
.size(960.0, 620.0),
|
|
)
|
|
.mount(view! {
|
|
JustifyContentGallery() {}
|
|
})
|
|
.run()
|
|
.await
|
|
}
|
|
|
|
#[component]
|
|
fn JustifyContentGallery() -> impl IntoView {
|
|
let canvas = Color::rgb(0x10, 0x16, 0x22);
|
|
let panel = Color::rgb(0x1A, 0x23, 0x33);
|
|
let accent = Color::rgb(0x71, 0xA7, 0xF7);
|
|
let text_color = Color::rgb(0xF5, 0xF7, 0xFB);
|
|
let muted = Color::rgb(0x9A, 0xA9, 0xC2);
|
|
|
|
view! {
|
|
column(gap = 18.0, padding = 24.0, background = canvas) {
|
|
text(role = TextRole::Heading(1), size = 28.0, weight = FontWeight::Semibold, color = text_color) {
|
|
"justify_content"
|
|
}
|
|
text(color = muted, wrap = TextWrap::Word) {
|
|
"Each cell below is the same width and contains the same four boxes. The only \
|
|
thing that changes between cells is `justify_content`, which controls how the \
|
|
leftover space along the main axis is distributed."
|
|
}
|
|
|
|
row(gap = 16.0, align_items = AlignItems::Start) {
|
|
column(gap = 14.0, flex = 1.0) {
|
|
JustifyRow(
|
|
label = "Start",
|
|
description = "Pack children at the start of the main axis (default).",
|
|
justify = JustifyContent::Start,
|
|
panel = panel,
|
|
accent = accent,
|
|
text_color = text_color,
|
|
muted = muted,
|
|
) {}
|
|
JustifyRow(
|
|
label = "End",
|
|
description = "Pack children at the end of the main axis.",
|
|
justify = JustifyContent::End,
|
|
panel = panel,
|
|
accent = accent,
|
|
text_color = text_color,
|
|
muted = muted,
|
|
) {}
|
|
JustifyRow(
|
|
label = "Center",
|
|
description = "Pack children as a group, centered on the main axis.",
|
|
justify = JustifyContent::Center,
|
|
panel = panel,
|
|
accent = accent,
|
|
text_color = text_color,
|
|
muted = muted,
|
|
) {}
|
|
}
|
|
column(gap = 14.0, flex = 1.0) {
|
|
JustifyRow(
|
|
label = "SpaceBetween",
|
|
description = "First child flush with the start, last with the end, equal gaps between.",
|
|
justify = JustifyContent::SpaceBetween,
|
|
panel = panel,
|
|
accent = accent,
|
|
text_color = text_color,
|
|
muted = muted,
|
|
) {}
|
|
JustifyRow(
|
|
label = "SpaceAround",
|
|
description = "Equal space around each child; end gaps are half the gap between children.",
|
|
justify = JustifyContent::SpaceAround,
|
|
panel = panel,
|
|
accent = accent,
|
|
text_color = text_color,
|
|
muted = muted,
|
|
) {}
|
|
JustifyRow(
|
|
label = "SpaceEvenly",
|
|
description = "Equal space between children and between children and both edges.",
|
|
justify = JustifyContent::SpaceEvenly,
|
|
panel = panel,
|
|
accent = accent,
|
|
text_color = text_color,
|
|
muted = muted,
|
|
) {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
fn JustifyRow(
|
|
label: &'static str,
|
|
description: &'static str,
|
|
justify: JustifyContent,
|
|
panel: Color,
|
|
accent: Color,
|
|
text_color: Color,
|
|
muted: Color,
|
|
) -> impl IntoView {
|
|
view! {
|
|
column(
|
|
gap = 6.0,
|
|
padding = 12.0,
|
|
background = panel,
|
|
border_radius = 10.0,
|
|
border = (1.0, accent),
|
|
) {
|
|
row(gap = 10.0, align_items = AlignItems::Center) {
|
|
text(size = 16.0, weight = FontWeight::Semibold, color = text_color) { label }
|
|
text(color = muted) { description }
|
|
}
|
|
row(
|
|
width = TRACK_WIDTH,
|
|
height = ITEM_SIZE + 16.0,
|
|
padding = 8.0,
|
|
gap = 8.0,
|
|
background = Color::rgba(0xFF, 0xFF, 0xFF, 0x10),
|
|
border_radius = 6.0,
|
|
align_items = AlignItems::Center,
|
|
justify_content = justify,
|
|
) {
|
|
JustifyItem(label = "1", accent = accent, text_color = text_color) {}
|
|
JustifyItem(label = "2", accent = accent, text_color = text_color) {}
|
|
JustifyItem(label = "3", accent = accent, text_color = text_color) {}
|
|
JustifyItem(label = "4", accent = accent, text_color = text_color) {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
fn JustifyItem(label: &'static str, accent: Color, text_color: Color) -> impl IntoView {
|
|
view! {
|
|
block(
|
|
width = ITEM_SIZE,
|
|
height = ITEM_SIZE,
|
|
background = accent,
|
|
border_radius = 6.0,
|
|
align_items = AlignItems::Center,
|
|
) {
|
|
row(
|
|
flex = 1.0,
|
|
align_items = AlignItems::Center,
|
|
justify_content = JustifyContent::Center,
|
|
) {
|
|
text(size = 18.0, weight = FontWeight::Semibold, color = text_color) { label }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn gallery_renders_all_labels() {
|
|
let root = JustifyContentGallery::builder().children(());
|
|
let view = ruin_app::__render_mountable_for_test(&root);
|
|
let snapshot = ruin_ui::layout_snapshot(1, UiSize::new(960.0, 620.0), view.element());
|
|
|
|
for label in ["Start", "End", "Center", "SpaceBetween", "SpaceAround", "SpaceEvenly"] {
|
|
assert!(
|
|
snapshot.scene.items.iter().any(|item| matches!(
|
|
item,
|
|
ruin_ui::DisplayItem::Text(text) if text.text.contains(label)
|
|
)),
|
|
"expected `{label}` label to appear in the rendered scene",
|
|
);
|
|
}
|
|
}
|
|
}
|