Components Guide

A walkthrough of OpenTUI’s built-in components with practical examples. All examples use the imperative (construct) API; the same components work identically in SolidJS (<box>) and React (<box>).

Box

The container component. Everything that needs border, background, or child layout uses Box.

import { Box, Text } from "@opentui/core"

// Basic bordered box
Box(
  { border: true, borderStyle: "rounded", padding: 1 },
  Text({ content: "Inside a box" }),
)

// Available border styles: "single", "double", "rounded", "bold", "ascii"
// Custom border characters are also supported via customBorderChars

Key props:

  • border: boolean - enable border
  • borderStyle: string - border character style
  • borderColor: string - border color (hex)
  • backgroundColor: string - fill color
  • title: string - text shown in the border
  • focusedBorderColor: string - border color when focused
  • All flexbox layout props (flexDirection, padding, gap, etc.)

Text

Read-only styled text display.

import { Text } from "@opentui/core"
import { StyledText } from "@opentui/core"

// Simple text
Text({ content: "Hello world", fg: "#00FF00" })

// Styled text with mixed formatting
const styled = StyledText.fromAnsi("\x1b[1mBold\x1b[0m and \x1b[3mitalic\x1b[0m")
Text({ content: styled })

// Text wrapping
Text({ content: "Long text that wraps...", wrap: "word" })

Key props:

  • content: string | StyledText - the text to display
  • fg: string - foreground color
  • bg: string - background color
  • bold: boolean, italic: boolean, underline: boolean, strikethrough: boolean
  • wrap: "word" | "char" | "none" - wrapping mode
  • truncation: "end" | "start" | "middle" - how to truncate when space is limited

Input

Single-line text input with cursor.

import { Input } from "@opentui/core"

const input = Input({
  placeholder: "Enter your name...",
  width: 30,
  onChange: (value) => {
    console.log("Current value:", value)
  },
  onSubmit: (value) => {
    console.log("Submitted:", value)
  },
})

input.focus()  // give it keyboard focus

Key props:

  • placeholder: string - shown when empty
  • value: string - current text value
  • password: boolean - mask input
  • onChange: (value: string) => void - fires on every keystroke
  • onSubmit: (value: string) => void - fires on Enter

Select

Dropdown/list selection.

import { Select } from "@opentui/core"

Select({
  options: [
    { label: "Option A", value: "a" },
    { label: "Option B", value: "b" },
    { label: "Option C", value: "c" },
  ],
  onSelect: (option) => {
    console.log("Selected:", option.value)
  },
})

TabSelect

Horizontal tab selector.

import { TabSelect } from "@opentui/core"

TabSelect({
  options: [
    { label: "Files", value: "files" },
    { label: "Search", value: "search" },
    { label: "Settings", value: "settings" },
  ],
  onSelect: (option) => {
    console.log("Tab:", option.value)
  },
})

ScrollBox

Scrollable container for content that exceeds its bounds.

import { ScrollBox, Text } from "@opentui/core"

ScrollBox(
  { width: 40, height: 10 },
  // Content taller than 10 rows will scroll
  ...Array.from({ length: 50 }, (_, i) =>
    Text({ content: `Line ${i + 1}` })
  ),
)

Supports mouse scroll and programmatic scrolling via scrollTo(), scrollBy().

Code

Syntax-highlighted code display using tree-sitter.

import { Code, SyntaxStyle, RGBA } from "@opentui/core"

const syntaxStyle = SyntaxStyle.fromStyles({
  default: { fg: RGBA.fromHex("#D4D4D4") },
  keyword: { fg: RGBA.fromHex("#C586C0") },
  string: { fg: RGBA.fromHex("#CE9178") },
  comment: { fg: RGBA.fromHex("#6A9955") },
  function: { fg: RGBA.fromHex("#DCDCAA") },
})

Code({
  content: `function greet(name: string) {\n  return "Hello, " + name\n}`,
  filetype: "typescript",
  syntaxStyle,
})

Gotcha: Tree-sitter is a peer dependency (web-tree-sitter). You need to install it separately and ensure the language WASM files are available.

Markdown

Renders markdown content with styling.

import { MarkdownRenderable } from "@opentui/core"

const md = new MarkdownRenderable(renderer, {
  id: "docs",
  content: "# Hello\n\nThis is **bold** and *italic*.\n\n- List item 1\n- List item 2",
})

Uses the marked library internally. Supports headers, bold, italic, lists, code blocks, and links.

Diff

Unified or split diff viewer.

import { DiffRenderable } from "@opentui/core"

const diff = new DiffRenderable(renderer, {
  id: "diff",
  oldContent: "line 1\nline 2\nline 3",
  newContent: "line 1\nline 2 modified\nline 3\nline 4",
})

FrameBuffer

Raw pixel-level drawing for custom graphics, animations, or effects.

import { FrameBuffer, RGBA } from "@opentui/core"

const fb = FrameBuffer({ width: 40, height: 20 })
// Draw directly to the buffer in renderAfter callback

This is what enables the 3D demos and shader examples in the repo.

ASCIIFont

Large ASCII art text using various font styles.

import { ASCIIFont } from "@opentui/core"

ASCIIFont({
  text: "HELLO",
  font: "tiny",  // available: "tiny", "block", "slick", "shade", "grid", "huge", "pallet"
  fg: "#FF6600",
})

Composing Components

Build reusable components as functions:

function StatusBar(props: { left: string; right: string }) {
  return Box(
    {
      flexDirection: "row",
      justifyContent: "space-between",
      width: "100%",
      backgroundColor: "#333333",
      padding: 0,
      paddingLeft: 1,
      paddingRight: 1,
    },
    Text({ content: props.left, fg: "#FFFFFF" }),
    Text({ content: props.right, fg: "#888888" }),
  )
}

function AppLayout(props: { title: string }, ...children: any[]) {
  return Box(
    { flexDirection: "column", width: "100%", height: "100%" },
    StatusBar({ left: props.title, right: "v1.0" }),
    Box({ flexGrow: 1, padding: 1, flexDirection: "column" }, ...children),
  )
}

// Use it
renderer.root.add(
  AppLayout(
    { title: "My App" },
    Text({ content: "Welcome!" }),
    Input({ placeholder: "Search..." }),
  ),
)

Colors

OpenTUI supports true color (24-bit). Use hex strings anywhere a color is accepted:

Text({ content: "Red text", fg: "#FF0000" })
Box({ backgroundColor: "#1E1E2E" })

// With alpha (RGBA)
Box({ backgroundColor: "#FF000080" })  // 50% transparent red

The RGBA class provides programmatic color manipulation:

import { RGBA } from "@opentui/core"

const color = RGBA.fromHex("#FF6600")
const transparent = color.withAlpha(128)

Next Steps