Skip to content

Layout System ​

Termina uses a declarative, tree-based layout system inspired by modern UI frameworks. Instead of imperatively positioning elements, you describe your UI as a tree of layout nodes and let the framework handle measurement and rendering.

Layout demo: vertical, horizontal, panel, and nested layouts in a 2x2 grid

Vertical, horizontal, panel, and nested layouts.

How It Works ​

Every UI in Termina is built by implementing BuildLayout() in your page:

csharp
public class MyPage : ReactivePage<MyViewModel>
{
    protected override ILayoutNode BuildLayout()
    {
        return Layouts.Vertical()
            .WithChild(new TextNode("Header").Height(1))
            .WithChild(new TextNode("Content").Fill())
            .WithChild(new TextNode("Footer").Height(1));
    }
}

The layout system processes your node tree in two phases:

1. Measure Phase ​

Starting from the root, each node is asked how much space it needs given the available space. Container nodes recursively measure their children.

Available: 80x24 (terminal size)
    └─ VerticalLayout measures children
        ├─ Header: 1 row (Fixed)
        ├─ Content: 22 rows (Fill = remaining)
        └─ Footer: 1 row (Fixed)

2. Render Phase ​

Once measurements are complete, each node is given its final bounds and renders its content to the terminal.

Layout Nodes vs. Container Nodes ​

Layout Nodes render content directly:

  • TextNode - Text with styling
  • PanelNode - Bordered panel with title
  • SpinnerNode - Animated spinner
  • TextInputNode - User text input

Container Nodes arrange children:

  • VerticalLayout - Stack children top-to-bottom
  • HorizontalLayout - Stack children left-to-right
  • GridNode - 2D grid with consistent column/row sizing
  • StackLayout - Overlay children (z-stack)
  • ScrollableContainerNode - Scrollable content area

Fluent API ​

All layout nodes support a fluent API for configuration:

csharp
new TextNode("Hello")
    .WithForeground(Color.Cyan)
    .Bold()
    .Height(1)
    .Width(SizeConstraint.Fill());

Container nodes use .WithChild() to add children:

csharp
Layouts.Vertical()
    .WithChild(header)
    .WithChild(content)
    .WithChild(footer);

Size Constraints ​

Every node has HeightConstraint and WidthConstraint properties that control sizing. The four constraint types are:

ConstraintDescriptionExample
Fixed(n)Exactly n rows/columns.Height(3)
Fill(weight)Take remaining space.Fill()
AutoSize to content.HeightAuto()
Percent(n)n% of available space.Height(SizeConstraint.Percent(50))

See Size Constraints for details.

Next Steps ​

Released under the Apache 2.0 License.