Layout
Box model and flex‑like composition.
Layout model
Cascade layout is box-based and uses a Yoga-like flex engine. Every element participates in layout, so you can build complex terminal UIs without manually computing coordinates.
In practice, you will spend most of your time with:
- flexDirection
- justifyContent
- alignItems
- width / height
- flexGrow / flexShrink
- padding / margin
- position + offsets for overlays
Flexbox basics
Use a row container to place panels side-by-side. One panel can be fixed width, the other can grow to fill remaining space.
<box flexDirection="row" width="100%" height="100%" padding={1}>
<box width={24} border padding={1}>
<text content="Sidebar" />
</box>
<box flexGrow={1} border padding={1}>
<text content="Main content" />
</box>
</box>Use justifyContent to distribute children along the main axis and alignItems along the cross axis.
<box flexDirection="row" justifyContent="space-between" alignItems="center" width="100%" height={3}>
<text content="Left" />
<text content="Center" />
<text content="Right" />
</box>Sizing (fixed, percentage, grow/shrink)
You can mix fixed and percentage sizing. Use fixed sizes for navigation sidebars and toolbars, and use flex growth for main content.
Guideline: if a child should fill remaining space, set flexGrow to 1. If it should stay fixed, keep flexGrow at 0 and provide an explicit width/height.
<box flexDirection="row" width="100%" height={10}>
<box width="30%" border />
<box width="70%" border />
</box>Positioning and overlays
Use absolute positioning for overlays: toasts, tooltips, modals, floating help. Keep overlays in a dedicated layer (higher zIndex) when you have multiple stacked elements.
<box width="100%" height="100%">
<box flexGrow={1} border />
<box position="absolute" right={1} bottom={1} border padding={1} backgroundColor="#24283b">
<text content="Saved" />
</box>
</box>Imperative layout
In imperative code you set the same flex properties directly on renderables. This approach is useful when you want to compute sizes from terminal dimensions.
import { BoxRenderable, TextRenderable } from "@cascadetui/core"
const header = new BoxRenderable(renderer, { height: 3, border: true, alignItems: "center" })
header.add(new TextRenderable(renderer, { content: "LAYOUT DEMO" }))
const content = new BoxRenderable(renderer, { flexGrow: 1, flexDirection: "row" })
const sidebar = new BoxRenderable(renderer, { width: 24, border: true })
const main = new BoxRenderable(renderer, { flexGrow: 1, border: true, marginLeft: 1 })
content.add(sidebar)
content.add(main)
renderer.root.add(header)
renderer.root.add(content)