Layout
Fleury lays out whole terminal cells. Parents describe the space available, children choose a size within it, and the parent positions them. In practice, most interfaces come from a small set of composable widgets:
| You need to… | Use |
|---|---|
| Arrange children horizontally or vertically | Row and Column |
| Give a child the remaining space | Expanded |
| Add a fixed gap or bound | SizedBox |
| Add space inside a region | Padding |
| Adapt to the local width | LayoutBuilder |
Build a responsive workspace
Section titled “Build a responsive workspace”This workspace uses fixed gaps, weighted panes, and one local breakpoint. The same child becomes two panes when wide and a vertical stack when narrow:
Activate Narrow and Wide to change only the workspace’s parent width.
The heading confirms which branch LayoutBuilder selected. This is the same
behavior a pane gets when its window, neighboring sidebar, or embedding surface
changes size.
Rows and columns
Section titled “Rows and columns”Row lays out children horizontally and Column vertically. Their main axis
follows that direction; the cross axis runs across it:
Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Project'), Text(project.name), ],)Use mainAxisAlignment to distribute children along the main axis and
crossAxisAlignment to align them across it. stretch fills the available
cross-axis space. Set mainAxisSize: MainAxisSize.min when a row or column
should hug its contents instead of taking all available space.
Fixed and flexible space
Section titled “Fixed and flexible space”Children start at their natural size. Wrap a child in Expanded when it should
take the main-axis space left after fixed children and gaps:
Row( children: [ const SizedBox(width: 18, child: Sidebar()), const SizedBox(width: 1), const Expanded(child: Editor()), ],)Multiple expanded children divide the space by flex. In the workspace demo,
2 and 3 make Files receive two-fifths and Preview three-fifths. A cell left
over from integer division goes to the earliest flexible child.
Flexible(fit: FlexFit.loose) offers a child up to its share without forcing
it to fill. Spacer() is an expanded empty gap; SizedBox is a fixed gap or
bound.
Spacing and framing
Section titled “Spacing and framing”Padding adds interior space in whole cells:
Padding( padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 1), child: ProjectDetails(),)Use Container when size, margin, padding, background, border, and alignment
belong to one visual region:
Container.filled( width: 28, padding: const EdgeInsets.all(1), border: const BoxBorder(style: BorderStyle.rounded), child: const Text('Build complete'),)Container.filled paints the theme’s surface color behind its content. The
plain Container constructor paints no background unless you pass color, so
it can sit on a region that is already styled. Container.framed fills like
Container.filled and also draws the theme’s border.
Container width and height are outer dimensions, including the border. A 28-cell bordered container has 26 interior columns before padding.
Responsive layout
Section titled “Responsive layout”LayoutBuilder reads the constraints of the exact place where it appears.
Use it when a reusable pane should respond to its own width, as in the demo.
An unbounded maximum, such as the width inside a horizontal scroll view, is
null. That is why the demo reads constraints.maxCols ?? 0.
MediaQuery.sizeOf(context) reads the entire surface size and rebuilds on
resize. Use it for app-wide decisions such as hiding global chrome below a
terminal width; prefer LayoutBuilder for components nested inside that app.
final surface = MediaQuery.sizeOf(context);final compact = surface.cols < 80;Both react automatically when a terminal or browser surface resizes. You do not listen to resize events yourself.
Advanced patterns
Section titled “Advanced patterns”Direct constraints
Section titled “Direct constraints”ConstrainedBox adds minimum or maximum dimensions without overriding a
tighter parent:
ConstrainedBox( minWidth: 24, maxWidth: 48, child: SearchPanel(results: results),)IntrinsicWidth and IntrinsicHeight ask a child for its natural extent. They
are useful for matching a small group to its widest label, but require an extra
measurement pass; do not wrap large subtrees speculatively.
Wrap and stack
Section titled “Wrap and stack”Wrap flows children into another run when the next one no longer fits:
Wrap( spacing: 1, runSpacing: 1, children: tags.map((tag) => Tag(label: tag)).toList(),)Stack paints children at one origin, with later children above earlier ones.
Use Positioned to place a child at a fixed left and top offset from the
stack’s top-left corner, optionally with a fixed width or height. Use
IndexedStack when one child is visible but inactive children must remain
mounted—for example, stateful tab bodies.
Aspect ratio and cell shape
Section titled “Aspect ratio and cell shape”AspectRatio uses cell counts, not physical pixels. Terminal cells are usually
taller than they are wide, so aspectRatio: 2.0 reads as visually square more
often than 1.0. Treat that as a presentation choice, not guaranteed terminal
geometry.
Overflow
Section titled “Overflow”When a row or column cannot fit its children, Fleury clips them. With Dart
assertions enabled, for example fleury run --enable-asserts, it also paints a
red ▓ marker on the overflowing edge; release builds and a plain dart run
only clip. Fix the constraint mismatch: add an Expanded, choose a compact
layout, bound the child, or make the content scroll.
API reference
Section titled “API reference”| API | What it does |
|---|---|
Row, Column, Flex | Arrange children on one main axis |
Expanded, Flexible, Spacer | Allocate remaining main-axis space |
SizedBox, ConstrainedBox | Add fixed or bounded dimensions |
Padding, Container | Add spacing and visual framing |
Center, Align | Position one child within available space |
LayoutBuilder | Builds from local CellConstraints |
MediaQuery.sizeOf | Reads the full surface size in cells |
Wrap, Stack, IndexedStack | Flow, layer, or preserve alternate children |
Next steps
Section titled “Next steps”- Lists & scrolling shows how to give long content a bounded viewport.
- Widgets & state covers stateless and
stateful widgets, the
Statelifecycle, keys, andBuildContext. - Browse the widget reference for the details of individual widgets.