GridWidget
Arrange child widgets in a two-dimensional grid with row and column spanning.
GridWidget is a layout container that positions children explicitly by row and column index. It supports fixed, content-based, and fill sizing for both columns and rows, with optional spanning across multiple rows or columns.
Basic Usage
Create a grid layout using the fluent API. Each cell is positioned with .Row() and .Column():
using Hex1b;
using Hex1b.Layout;
await using var terminal = Hex1bTerminal.CreateBuilder()
.WithHex1bApp((app, options) => ctx =>
ctx.Grid(g =>
{
g.Columns.Add(SizeHint.Fixed(22));
g.Columns.Add(SizeHint.Fill);
g.Rows.Add(SizeHint.Fixed(3));
g.Rows.Add(SizeHint.Fill);
g.Rows.Add(SizeHint.Fixed(1));
return [
g.Cell(c => c.Border(b => [
b.VStack(v => [
v.Text("📂 Files"),
v.Text("📊 Dashboard"),
v.Text("⚙️ Settings"),
])
]).Title("Navigation")).RowSpan(0, 3).Column(0),
g.Cell(c => c.Border(b => [
b.Text("Grid Layout Demo"),
]).Title("Header")).Row(0).Column(1),
g.Cell(c => c.Border(b => [
b.Text("Main content area")
]).Title("Content")).Row(1).Column(1),
g.Cell(c => c.Text(" Status: Ready")).Row(2).Column(1),
];
}))
.Build();
await terminal.RunAsync();dotnet runSimple Grid
Position cells by row and column index:
Cells default to row 0, column 0 with a span of 1. Use .Row(n) and .Column(n) to place them explicitly.
Row and Column Spanning
Cells can span multiple rows or columns using .RowSpan(row, span) and .ColumnSpan(col, span):
ctx.Grid(g => [
// Spans rows 0 and 1 in column 0
g.Cell(c => c.Text("Sidebar")).RowSpan(0, 2).Column(0).Width(20),
// Spans columns 0 and 1 in row 0
g.Cell(c => c.Text("Header")).Row(0).ColumnSpan(0, 2),
])2
3
4
5
6
7
.RowSpan(row, span)— Start atrow, occupyspanrows.ColumnSpan(col, span)— Start atcol, occupyspancolumns.Row(n)is shorthand for.RowSpan(n, 1).Column(n)is shorthand for.ColumnSpan(n, 1)
Sidebar Layout
A classic application layout with sidebar, header, and content area:
The sidebar spans both rows while the header and content each occupy one row in the second column.
Sizing Columns and Rows
Column Width
Set column widths directly on cells or through explicit definitions:
.Width(n)— Fixed width ofncharacters.FillWidth()— Fill remaining horizontal space.FillWidth(weight)— Fill with proportional weight
Row Height
Similarly for row heights:
.Height(n)— Fixed height ofnrows.FillHeight()— Fill remaining vertical space.FillHeight(weight)— Fill with proportional weight
Explicit Definitions
For more control, define columns and rows explicitly via GridContext:
ctx.Grid(g => {
g.Columns.Add(SizeHint.Fixed(20)); // Column 0: 20 chars wide
g.Columns.Add(SizeHint.Fill); // Column 1: fill remaining
g.Rows.Add(SizeHint.Fixed(3)); // Row 0: 3 rows tall
g.Rows.Add(SizeHint.Fill); // Row 1: fill remaining
return [
g.Cell(c => c.Text("Nav")).RowSpan(0, 2).Column(0),
g.Cell(c => c.Text("Header")).Row(0).Column(1),
g.Cell(c => c.Text("Content")).Row(1).Column(1),
];
})2
3
4
5
6
7
8
9
10
11
12
13
Auto-Created Definitions
Columns and rows not covered by explicit definitions are auto-created from cell positions with Content sizing (shrink to fit). You only need explicit definitions when you want Fill or Fixed sizing.
Layout Algorithm
GridWidget distributes space in two passes per axis:
- Fixed Pass: Fixed-size columns/rows get their exact size. Content-sized columns/rows are measured from their non-spanning cells, taking the maximum.
- Fill Pass: Remaining space is distributed among fill columns/rows proportionally by weight.
All children receive the full width and height of their cell (accounting for any spans).
Common Patterns
Dashboard Layout
ctx.Grid(g => {
g.Columns.Add(SizeHint.Fill);
g.Columns.Add(SizeHint.Fill);
g.Rows.Add(SizeHint.Fixed(1));
g.Rows.Add(SizeHint.Fill);
g.Rows.Add(SizeHint.Fill);
return [
g.Cell(c => c.Text("Dashboard")).Row(0).ColumnSpan(0, 2),
g.Cell(c => c.Border(b => [b.Text("Chart 1")]).Title("Sales"))
.Row(1).Column(0),
g.Cell(c => c.Border(b => [b.Text("Chart 2")]).Title("Users"))
.Row(1).Column(1),
g.Cell(c => c.Border(b => [b.Text("Details")]).Title("Activity"))
.Row(2).ColumnSpan(0, 2),
];
})2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Form with Labels
ctx.Grid(g => [
g.Cell(c => c.Text("Name:")).Row(0).Column(0).Width(12),
g.Cell(c => c.TextBox(nameState)).Row(0).Column(1).FillWidth(),
g.Cell(c => c.Text("Email:")).Row(1).Column(0),
g.Cell(c => c.TextBox(emailState)).Row(1).Column(1),
g.Cell(c => c.Text("Notes:")).Row(2).Column(0),
g.Cell(c => c.TextBox(notesState)).Row(2).Column(1),
])2
3
4
5
6
7
8
9
10
Related Widgets
- VStackWidget — For simple vertical layouts
- HStackWidget — For simple horizontal layouts
- BorderWidget — For adding borders to grid cells
- Splitter — For resizable split views