4.4 KiB

OpenTUI React (@opentui/react)

A React reconciler for building terminal user interfaces with familiar React patterns. Write TUIs using JSX, hooks, and component composition.

Overview

OpenTUI React provides:

  • Custom reconciler: React components render to OpenTUI renderables
  • JSX intrinsics: <text>, <box>, <input>, etc.
  • Hooks: useKeyboard, useRenderer, useTimeline, etc.
  • Full React compatibility: useState, useEffect, context, and more

When to Use React

Use the React reconciler when:

  • You're familiar with React patterns
  • You want declarative UI composition
  • You need React's ecosystem (context, state management libraries)
  • Building applications with complex state
  • Team knows React already

When NOT to Use React

Scenario Use Instead
Maximum performance critical @opentui/core (imperative)
Fine-grained reactivity @opentui/solid
Smallest bundle size @opentui/core
Building a framework/library @opentui/core

Quick Start

bunx create-tui@latest -t react my-app
cd my-app
bun run src/index.tsx

The CLI creates the my-app directory for you - it must not already exist.

Agent guidance: Always use autonomous mode with -t <template> flag. Never use interactive mode (bunx create-tui@latest my-app without -t) as it requires user prompts that agents cannot respond to.

Or manual setup:

mkdir my-tui && cd my-tui
bun init
bun install @opentui/react @opentui/core react
import { createCliRenderer } from "@opentui/core"
import { createRoot } from "@opentui/react"
import { useState } from "react"

function App() {
  const [count, setCount] = useState(0)
  
  return (
    <box border padding={2}>
      <text>Count: {count}</text>
      <box
        border
        onMouseDown={() => setCount(c => c + 1)}
      >
        <text>Click me!</text>
      </box>
    </box>
  )
}

const renderer = await createCliRenderer()
createRoot(renderer).render(<App />)

Core Concepts

JSX Elements

React maps JSX intrinsic elements to OpenTUI renderables:

// These are not HTML elements!
<text>Hello</text>           // TextRenderable
<box border>Content</box>    // BoxRenderable
<input placeholder="..." />  // InputRenderable
<select options={[...]} />   // SelectRenderable

Text Modifiers

Inside <text>, use modifier elements:

<text>
  <strong>Bold</strong>, <em>italic</em>, and <u>underlined</u>
  <span fg="red">Colored text</span>
  <br />
  New line with <a href="https://example.com">link</a>
</text>

Styling

Two approaches to styling:

// Direct props
<box backgroundColor="blue" padding={2} border>
  <text fg="#00FF00">Green text</text>
</box>

// Style prop
<box style={{ backgroundColor: "blue", padding: 2, border: true }}>
  <text style={{ fg: "#00FF00" }}>Green text</text>
</box>

Available Components

Layout & Display

  • <text> - Styled text content
  • <box> - Container with borders and layout
  • <scrollbox> - Scrollable container
  • <ascii-font> - ASCII art text

Input

  • <input> - Single-line text input
  • <textarea> - Multi-line text input
  • <select> - List selection
  • <tab-select> - Tab-based selection

Code & Diff

  • <code> - Syntax-highlighted code
  • <line-number> - Code with line numbers
  • <diff> - Unified or split diff viewer

Text Modifiers (inside <text>)

  • <span> - Inline styled text
  • <strong>, <b> - Bold
  • <em>, <i> - Italic
  • <u> - Underline
  • <br> - Line break
  • <a> - Link

Essential Hooks

import {
  useRenderer,
  useKeyboard,
  useOnResize,
  useTerminalDimensions,
  useTimeline,
} from "@opentui/react"

See API Reference for detailed hook documentation.

In This Reference

  • Configuration - Project setup, tsconfig, bundling
  • API - Components, hooks, createRoot
  • Patterns - State management, keyboard handling, forms
  • Gotchas - Common issues, debugging, limitations

See Also

  • Core - Underlying imperative API
  • Solid - Alternative declarative approach
  • Components - Component reference by category
  • Layout - Flexbox layout system
  • Keyboard - Input handling and shortcuts
  • Testing - Test renderer and snapshots