Layout
Tuika uses integer-native flex layout for application structure. Flex is the
general container, Flow is the concise choice for intrinsic items that wrap,
and Grid is a deliberately small equal-column grid. All three measure ordinary
third-party View implementations through the same MeasureRequest contract.
Flex containers and items
Container style controls direction, wrapping, padding, gaps, and alignment:
use tuika::prelude::*;
let tags = Flex::row()
.wrap(FlexWrap::Wrap)
.column_gap(1)
.row_gap(1)
.align_content(AlignContent::SpaceBetween)
.auto(element(Text::raw("rust")))
.auto(element(Text::raw("terminal-ui")));
# let _ = tags;align positions items within one line. align_content distributes the lines
themselves when wrapping creates more than one. justify distributes space on
each line. Use row_gap and column_gap when the two axes need different
spacing; gap sets both.
Child sizing belongs to FlexItemStyle, separately from the container:
# use tuika::prelude::*;
let item = FlexItemStyle::default()
.basis(Dimension::Fixed(12))
.grow(1)
.shrink(1)
.min_main(6)
.max_main(20)
.align_self(Align::Center);
let row = Flex::row().styled(item, element(Text::raw("resizable")));
# let _ = row;The basis is the starting main-axis size. Positive free space is shared by
grow; negative free space is removed according to shrink, without crossing
the item’s min/max constraints. Integer cells are assigned by rounding track
boundaries, so the final child reaches the exact container boundary without
losing or double-counting a cell.
Wrapping and line alignment
FlexWrap::Wrap starts a new line when the next item’s outer main size no
longer fits. Each line resolves grow, shrink, justification, and item alignment
independently. AlignContent::{Start, Center, End, Stretch, SpaceBetween} then
places completed lines on the cross axis. NoWrap remains the default.
Flow packages the common intrinsic wrapping case:
# use tuika::prelude::*;
let flow = Flow::new()
.gap(1)
.item(element(Text::raw("one")))
.item(element(Text::raw("two")))
.item(element(Text::raw("a-longer-item")));
# let _ = flow;Choose Flex when children need grow/shrink, fixed or percentage bases, or
per-item alignment. Choose Flow when every child is intrinsic and wrapping is
the main behavior.
Flow versus Grid
Flow packs variable-width items and wraps wherever the next item stops
fitting. Grid::new(columns) creates a fixed number of equal-width columns,
fills them row-major, and derives each row’s height from its tallest cell.
# use tuika::prelude::*;
let grid = Grid::new(3)
.column_gap(1)
.row_gap(1)
.cell(element(Text::raw("a")))
.cell(element(Text::raw("b")))
.cell(element(Text::raw("c")));
# let _ = grid;Grid intentionally omits CSS Grid’s named lines, implicit tracks, spanning, dense packing, and independent track definitions. Those features add a large constraint language while terminal applications usually need a stable column count and predictable clipping. Compose nested Flex/Grid containers when a screen needs a more irregular structure.
Measurement requests
View::measure_request receives optional known axes and an AvailableSpace
mode for unresolved axes:
Definite(n)means at mostncells are available.MinContentasks for the smallest useful intrinsic contribution.MaxContentasks for the preferred unconstrained contribution.known_widthandknown_heightmean the parent has already fixed that axis.
Flex and Grid preserve those modes when measuring third-party views and add a
known axis once a fixed basis or grid track has been resolved. Existing views
that only implement measure remain compatible through the default adapter.
Because MeasureRequest and AvailableSpace are non-exhaustive, downstream
implementations should match with a fallback arm so future request metadata can
be added compatibly.
Migrating existing layouts
LayoutStyle::gapbecame independentrow_gapandcolumn_gapfields. UseFlex::gap(n)when both should remain equal.Item::dimensionmoved intoItem::style.basis. PreferItem::styled(FlexItemStyle, intrinsic)for direct solver use.Flex::{auto,grow,fixed}remain concise compatibility builders. UseFlex::styledwhen shrink, min/max, or per-child alignment matters.- Existing no-wrap layouts keep their behavior unless
FlexWrap::Wrapis set.
The public solve_layout
result includes child rectangles and flex-line metadata for hosts that need hit
testing, scrolling, or layout inspection without painting.