Using Box
The Box module is the core of effect-boxes. A Box represents a rectangular
block of text with explicit dimensions that can be composed, aligned, and
transformed through functional composition.
Creating Boxes
The most common way to create a box is from a string. Multi-line strings are handled automatically.
import * as Box from "effect-boxes/Box";
const hello = Box.text("Hello\nWorld");
// 2 rows, 5 columnsHello
WorldOther constructors include Box.emptyBox(rows, cols) for blank space,
Box.char(c) for a single character, and Box.line(s) for a single-line box:
// An empty box with specific dimensions
const empty = Box.emptyBox(2, 10);
// A single character
const star = Box.char("*");
// A single-line box (strips newlines)
const oneLine = Box.line("Hello World");Text Flow
For longer text, para wraps content to a specified width, and columns
creates newspaper-style columnar layouts.
const paragraph = Box.para(
"The Box module is the core of the effect-boxes library, providing the fundamental data structures and operations for creating and composing rectangular text layouts. Boxes can be combined horizontally and vertically, aligned within larger spaces, and annotated with styling information for rich terminal output.",
Box.left,
50,
);The Box module is the core of the effect-boxes
library, providing the fundamental data structures
and operations for creating and composing
rectangular text layouts. Boxes can be combined
horizontally and vertically, aligned within larger
spaces, and annotated with styling information for
rich terminal output.const cols = Box.columns(
"The Box module is the core of the effect-boxes library...",
Box.left, // alignment
25, // column width
6, // column height
);
const layout = Box.hsep(cols, 2, Box.top);The Box module is the composing rectangular information for rich
core of the effect-boxes text layouts. Boxes can terminal output.
library, providing the be combined horizontally
fundamental data and vertically, aligned
structures and operations within larger spaces, and
for creating and annotated with stylingComposing Boxes
Boxes can be combined horizontally and vertically to build complex layouts.
Horizontal Composition
const row = Box.hcat(
[Box.text("Left"), Box.text(" | "), Box.text("Right")],
Box.top,
);Left | RightUse punctuateH to insert a separator between boxes, or hsep for spacing:
const table = Box.punctuateH(
[Box.text("Name"), Box.text("Age"), Box.text("City")],
Box.top,
Box.text(" | "),
);Name | Age | Cityconst spaced = Box.hsep(
[Box.text("A"), Box.text("B"), Box.text("C")],
3, // spaces between boxes
Box.top,
);A B CVertical Composition
const column = Box.vcat(
[Box.text("Top"), Box.text("Middle"), Box.text("Bottom")],
Box.left,
);Top
Middle
Bottomconst sections = Box.punctuateV(
[Box.text("Header"), Box.text("Content"), Box.text("Footer")],
Box.left,
Box.text("---"),
);Header
---
Content
---
FooterAppending Individual Boxes
For combining two boxes, use hAppend and vAppend:
const combined = pipe(Box.text("Hello "), Box.hAppend(Box.text("World")));Hello WorldAlignment and Positioning
Alignment
Control how a box is positioned within a larger space:
const centered = Box.alignHoriz(Box.text("Hello"), Box.center1, 20);┌────────────────────┐
│ Hello │
└────────────────────┘// Align both horizontally and vertically
const centered2d = Box.align(
Box.text("X"),
Box.center1, // horizontal
Box.center1, // vertical
3, // height
7, // width
);┌───────┐
│ │
│ X │
│ │
└───────┘Moving Boxes
Shift a box by adding empty space around it:
const positioned = pipe(Box.text("Hello"), Box.moveRight(5), Box.moveDown(2));┌──────────┐
│ │
│ │
│ Hello│
└──────────┘Available movement functions: moveRight, moveLeft, moveDown, moveUp.
Truncation
Truncate each line to a maximum width, inserting an ellipsis where content was removed. The position parameter controls which part of the text is kept.
const long = Box.text("This is a very long piece of text");
// Keep the beginning
pipe(long, Box.truncate(15, Box.left));
// Keep the end
pipe(long, Box.truncate(15, Box.right));
// Keep both ends
pipe(long, Box.truncate(15, Box.center1));This is a very…pipe(long, Box.truncate(15, Box.right));… piece of textpipe(long, Box.truncate(15, Box.center1));This is…of textIf the box is already within the target width, it is returned unchanged.
Annotations
Boxes are parameterized by an annotation type: Box<A>. Annotations are
metadata attached to a box's content that renderers interpret differently.
Use Box.annotate to attach an annotation:
import * as Ansi from "effect-boxes/Ansi";
const error = pipe(Box.text("Error!"), Box.annotate(Ansi.red));Error!The annotation type determines what styling is applied at render time:
- Ansi — Terminal colors and text effects (bold, underline, etc.)
- Cmd — Terminal control sequences (cursor movement, screen clearing)
- Html — HTML elements and attributes for web rendering
Each annotation type has a corresponding renderer that interprets it. See Using Ansi for terminal styling and the Rendering guide for how renderers process annotations.
Rendering
To get a string from a box, use the sync convenience functions:
const box = pipe(Box.text("Hello"), Box.annotate(Ansi.red))
// Strips all annotations
Box.renderPlainSync(box)Hello// Preserves ANSI styling
Box.renderPrettySync(box)HelloFor Effect-based rendering and the full renderer layer system, see the Rendering guide.