implement flexbox main axis justification
This commit is contained in:
194
lib/ruin_app/example/06_justify_content.rs
Normal file
194
lib/ruin_app/example/06_justify_content.rs
Normal file
@@ -0,0 +1,194 @@
|
||||
//! 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",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user