Box¶
Draws a container (optionally bordered) and lays out its children inside a padded content area.
Usage¶
import { ui } from "@rezi-ui/core";
ui.box({ title: "Settings", border: "rounded", p: 1 }, [
ui.text("Hello"),
]);
Props¶
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string |
- | Optional identity (not focusable) |
key |
string |
- | Reconciliation key |
title |
string |
- | Optional title rendered in the top border |
titleAlign |
"left" \| "center" \| "right" |
"left" |
Title alignment |
preset |
"card" \| "surface" \| "well" \| "elevated" |
- | Style preset applied before explicit props (e.g. card → rounded + p: 1) |
border |
"none" \| "single" \| "double" \| "rounded" \| "heavy" \| "dashed" \| "heavy-dashed" |
"single" |
Border style |
shadow |
boolean \| { offsetX?: number; offsetY?: number; density?: \"light\" \| \"medium\" \| \"dense\" } |
- | Shadow effect for depth |
style |
TextStyle |
- | Style applied to the box surface and inherited by children (bg fills the rect) |
borderStyle |
TextStyle |
- | Style applied only to the border and title; decouples border appearance from child style inheritance (see Style Propagation) |
opacity |
number |
1 |
Surface opacity in [0..1] (values are clamped) |
transition |
TransitionSpec |
- | Declarative render-time transition for position, size, and/or opacity |
p, px, py, pt, pr, pb, pl |
SpacingValue |
- | Padding props |
gap |
SpacingValue |
0 |
Vertical gap between children in the synthetic inner column layout |
m, mx, my |
SpacingValue |
- | Margin props |
width, height |
number \| \"auto\" \| \"${number}%\" |
- | Size constraints |
minWidth, maxWidth, minHeight, maxHeight |
number |
- | Size bounds (cells) |
flex |
number |
- | Main-axis flex in stacks |
flexShrink |
number |
0 |
Overflow shrink factor when box is a stack child |
flexBasis |
number \| \"auto\" \| \"full\" \| \"${number}%\" |
- | Initial main-axis basis before grow/shrink |
aspectRatio |
number |
- | Enforce width/height ratio |
alignSelf |
"auto" \| "start" \| "center" \| "end" \| "stretch" |
"auto" |
Per-child cross-axis alignment override in parent stack |
position |
"static" \| "absolute" |
"static" |
Absolute positioning mode as a stack child |
top, right, bottom, left |
number |
- | Absolute offsets when position: "absolute" |
gridColumn, gridRow |
number |
- | 1-based explicit grid placement coordinates when parent is ui.grid(...) |
colSpan, rowSpan |
number |
1 |
Grid span across columns/rows when parent is ui.grid(...) |
Examples¶
0) Preset card (recommended)¶
import { ui } from "@rezi-ui/core";
ui.box({ preset: "card" }, [
ui.text("Card title", { variant: "heading" }),
ui.text("Body text"),
]);
1) Card-like panel with background¶
import { ui, rgb } from "@rezi-ui/core";
ui.box({ border: "rounded", p: 1, style: { bg: rgb(18, 18, 24) } }, [
ui.text("Card title", { style: { bold: true } }),
ui.text("Body text"),
]);
2) Sidebar + content layout¶
import { ui } from "@rezi-ui/core";
ui.row({ gap: 1 }, [
ui.box({ width: 24, border: "single", p: 1, title: "Sidebar" }, [
ui.column({ gap: 1 }, [ui.text("One"), ui.text("Two")]),
]),
ui.box({ flex: 1, border: "single", p: 1, title: "Content" }, [
ui.text("Main area"),
]),
]);
3) Decoupled border style¶
Use borderStyle to style the border and title independently from children. Without it, style attributes (e.g. fg, bold) propagate to all descendants via parentStyle, which can break child widget rendering (syntax highlighting, custom fg colors, etc.).
import { ui, rgb } from "@rezi-ui/core";
// Border is bold orange, but children inherit default fg (not orange)
ui.box(
{
title: " Editor ",
border: "heavy",
borderStyle: { fg: rgb(255, 160, 50), bold: true },
p: 0,
},
[ui.codeEditor({ id: "editor", /* ... */ })],
);
Without borderStyle (using only style), the fg and bold would propagate to the code editor and override syntax highlighting. borderStyle prevents this by keeping border/title appearance separate from child style inheritance.
4) Declarative transition (size + opacity)¶
import { ui } from "@rezi-ui/core";
ui.box(
{
id: "details-panel",
width: state.expanded ? 48 : 28,
opacity: state.expanded ? 1 : 0.65,
border: "rounded",
p: 1,
transition: {
duration: 220,
easing: "easeInOutCubic",
properties: ["size", "opacity"],
},
},
[ui.text("Animated container")],
);
5) Box child gap¶
import { ui } from "@rezi-ui/core";
ui.box({ border: "single", p: 1, gap: 1, title: "Events" }, [
ui.text("Connected"),
ui.text("Sync complete"),
ui.text("Watcher started"),
]);
Style Propagation¶
ui.box() merges its resolved style into parentStyle, which is passed to all child widgets. This means any fg, bg, bold, dim, etc. set on style will be inherited by every descendant unless overridden.
When borderStyle is set:
- The border and title use
borderStylemerged with the base parent style - Children use
stylemerged with the base parent style (withoutborderStylemixed in) - This cleanly separates border chrome from content styling
When borderStyle is NOT set (default, backward compatible):
- Both the border and children use the same merged
style - This is the traditional behavior and works well when the box style is purely
bg-based
Rule of thumb: If your box style includes fg, bold, dim, or other text attributes intended only for the border/title, use borderStyle instead. If your box style is only bg, style alone is fine.
Notes¶
- Borders consume 1 cell on each edge (unless
border: "none"). - Padding is applied inside the border and reduces child content area.
gapis applied inside the content rect (after border + padding). Defaultgap: 0preserves contiguous child flow.- Absolute-positioned children inside a box are removed from normal inner-column flow, then laid out in a second pass relative to the box content rect.
transition.propertiesdefaults to"all"when omitted (position,size,opacity).transition.properties: []disables animation tracks for that box.
Mouse Wheel Scrolling¶
Boxes with overflow: "scroll" now respond to mouse wheel events.
The wheel scrolls the nearest scrollable ancestor under the cursor.
ui.box({
overflow: "scroll",
scrollX: state.scrollX,
scrollY: state.scrollY,
height: 10,
}, [
// content taller than 10 rows
]);
Related¶
- Layout - Borders, padding, nesting
- Animation - Motion hooks and transition props
- Row / Column - Stack layouts
- Style Props - TextStyle reference and inheritance rules