//! 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", ); } } }