Intrinsic Elements
The built-in JSX tags box, text, input, select that Gridland renders to a cell grid instead of the DOM
In a normal React app, JSX tags like <div>, <span>, and <button> compile to DOM elements. In Gridland, you use a different set of tags <box>, <text>, <input>, <select>, and a few others that compile to cell grid primitives, not DOM. They're drawn to an HTML5 <canvas> in the browser and to real stdout in a terminal, never to the document tree.
Run demo
bunx @gridland/demo primitivescurl -fsSL https://raw.githubusercontent.com/thoughtfulllc/gridland/main/scripts/run-demo.sh | bash -s primitivesThese are JSX intrinsic elements, not DOM elements. <box> renders to the
canvas cell grid, not to an HTML <div>. They only work inside a
<TUI> wrapper.
Files that use intrinsic elements must start with // @ts-nocheck at the very
top. The JSX type definitions for <box>, <text>, etc. conflict with React's
default DOM types, and TypeScript will reject the file without this directive.
This is a known limitation of the OpenTUI JSX integration.
All primitives accept pointer event handlers (onClick, onMouseOver, onMouseScroll, and
eight others). See the Pointer Events reference for the
complete handler list and event payload shape.
<box>
A container element with flexbox layout support.
<box
flexDirection="column"
padding={1}
border
borderStyle="rounded"
borderColor="#5e81ac"
backgroundColor="#2e3440"
>
{children}
</box>Box Props
| Prop | Type | Description |
|---|---|---|
flexDirection | "row" | "column" | Layout direction |
padding | number | Padding in cells |
margin | number | Margin in cells |
border | boolean | Show border |
borderStyle | "single" | "rounded" | "double" | "heavy" | "dashed" | Border style |
borderColor | string | Border color (hex) |
backgroundColor | string | Background color (hex) |
title | string | Border title text |
titleAlignment | "left" | "center" | "right" | Title position |
flexGrow | number | Flex grow factor |
flexShrink | number | Flex shrink factor |
width | number | string | Width in cells or percentage |
height | number | string | Height in cells or percentage |
gap | number | Gap between children |
<text>
Renders styled text content.
<text fg="#a3be8c" bold>
Hello World
</text>Text Props
| Prop | Type | Description |
|---|---|---|
fg | string | Foreground color (hex) |
bg | string | Background color (hex) |
bold | boolean | Bold text |
italic | boolean | Italic text |
underline | boolean | Underlined text |
dim | boolean | Dimmed text |
<input>
A text input field.
<input> is terminal-only. It is backed by OpenTUI's Zig-FFI
EditBuffer and will crash with a resolveRenderLib error if rendered
inside <TUI> in the browser (docs site, @gridland/web, any canvas
runtime). Use TextInput from
@/components/ui/text-input in browser demos — it provides the same
behavior with a pure-JS implementation.
<input
placeholder="Type here..."
onInput={(value) => console.log(value)}
onSubmit={(value) => console.log("Submitted:", value)}
/><select>
A selection list.
<select
options={[
{ label: "Option A", value: "a" },
{ label: "Option B", value: "b" },
]}
onChange={(index, option) => console.log(option)}
/><scrollbox>
A scrollable container.
<scrollbox height={10}>
{/* Content taller than 10 rows will scroll */}
</scrollbox><code>
Syntax-highlighted code block.
<code content="const x = 42" filetype="typescript" /><markdown>
Rendered markdown content.
<markdown content="# Hello\n\nThis is **bold** text." />