▚TextTable
Lays out a two-dimensional array of styled text cells. Supports intrinsic or full-width columns, constrained wrapping, independent inner and outer borders, cell padding, and text selection.
TextTable currently has an imperative renderable API. It is not registered as a built-in React or Solid component.
##Basic usage
1import { TextTableRenderable, bold, fg, type TextChunk, type TextTableContent } from "@opentui/core"23const cell = (text: string): TextChunk[] => [{ __isChunk: true, text }]45const content: TextTableContent = [6[[bold("Service")], [bold("Status")], [bold("Notes")]],7[cell("api"), [fg("#00d4aa")("OK")], cell("latency 28ms")],8[cell("worker"), [fg("#b8a0ff")("DEGRADED")], cell("queue depth: 124")],9]1011const table = new TextTableRenderable(renderer, {12width: "100%",13wrapMode: "word",14columnWidthMode: "content",15borderStyle: "rounded",16content,17})1819renderer.root.add(table)
##Content
Cell content is styled-text chunks. null, undefined, and missing cells render as empty text. Rows may have different lengths — the table uses the longest row's column count and fills missing cells with empty content.
1type TextTableCellContent = TextChunk[] | null | undefined2type TextTableContent = TextTableCellContent[][]
The first row has no special behavior. Styling it as a header is a convention — TextTable has no header option.
Replace data at runtime:
1table.content = [2[[bold("Name")], [bold("State")]],3[cell("worker-1"), [fg("#22c55e")("ready")]],4]
##Column sizing
- ▸
columnWidthMode: "full"— expand columns evenly to fill the width constraint (default) - ▸
columnWidthMode: "content"— keep the table at intrinsic width - ▸
columnFitter: "proportional"— preserve width for intrinsically wider columns (default) - ▸
columnFitter: "balanced"— keep constrained columns closer to even width - ▸
wrapMode: "word" | "char"— shrink columns and grow rows when content is wider than the constraint
##Borders and spacing
1// Outer border without inner cell separators2const table = new TextTableRenderable(renderer, {3border: false,4outerBorder: true,5content,6})78// Gap between columns when inner vertical borders are off9{10border: false,11columnGap: 2,12}1314// Padding per cell15{16cellPadding: 1,17cellPaddingX: 2, // override per axis18cellPaddingY: 1,19}
showBorders: false suppresses border glyph painting without removing the space reserved by enabled borders.
##Selection
Selection starts only within cell content. A vertical drag that stays in the anchor column selects that column; moving into another column switches to grid selection.
1renderer.on("selection", () => {2console.log(table.getSelectedText())3})45table.shouldStartSelection(x, y) // is the position selectable?6table.hasSelection()7table.getSelection() // first cell's { start, end } or null
##Options
| prop | type | default | description |
|---|---|---|---|
| content | TextTableContent[] | - | Rows of styled cell chunks |
| wrapMode | "none" | "char" | "word" | "word" | Cell text wrapping behavior |
| columnWidthMode | "content" | "full" | "full" | Preserve intrinsic width or fill constraint |
| columnFitter | "proportional" | "balanced" | "proportional" | Width allocation when columns must shrink |
| cellPadding | number | 0 | Padding on each side of a cell |
| cellPaddingX / cellPaddingY | number | cellPadding | Per-axis padding |
| columnGap | number | 0 | Gap between columns when inner vertical borders are off |
| showBorders | boolean | true | Paint enabled border glyphs |
| border | boolean | true | Enable inner row and column separators |
| outerBorder | boolean | border | Enable the table boundary |
| borderStyle | "single" | "double" | "rounded" | "heavy" | "single" | Border glyph set |
| borderColor | ColorInput | "#FFFFFF" | Border foreground color |
| backgroundColor | ColorInput | transparent | Buffered table surface background |
| fg / bg | ColorInput | "#FFFFFF" / transparent | Default cell text colors |
| selectable | boolean | true | Allow cell text selection |