Skip to main content

Overview

The TextareaRenderable component provides a powerful multi-line text editing experience with support for text wrapping, selection, undo/redo, and extensive keyboard shortcuts. It extends EditBufferRenderable with rich text editing capabilities.

Basic Usage

import { Screen, TextareaRenderable } from "@opentui/core"

const screen = new Screen()
const ctx = screen.createContext()

const textarea = new TextareaRenderable(ctx, {
  x: 5,
  y: 5,
  width: 50,
  height: 10,
  initialValue: "Hello, world!",
  placeholder: "Start typing...",
})

screen.append(textarea)
textarea.focus()

Props

initialValue
string
Initial text content (can include newlines)
placeholder
StyledText | string | null
default:"null"
Placeholder shown when textarea is empty. Can be plain text or styled text.
backgroundColor
ColorInput
default:"'transparent'"
Background color when unfocused
textColor
ColorInput
default:"'#FFFFFF'"
Text color when unfocused
focusedBackgroundColor
ColorInput
default:"backgroundColor"
Background color when focused (falls back to backgroundColor)
focusedTextColor
ColorInput
default:"textColor"
Text color when focused (falls back to textColor)
placeholderColor
ColorInput
default:"'#666666'"
Color of placeholder text
keyBindings
KeyBinding[]
Custom key bindings to override or extend default shortcuts
keyAliasMap
KeyAliasMap
Custom key aliases for remapping keyboard shortcuts
onSubmit
(event: SubmitEvent) => void
Callback fired when submit action is triggered (Meta+Enter)

Inherited Props from EditBufferRenderable

height
number
Height in terminal rows
minHeight
number
Minimum height for flex layouts
maxHeight
number
Maximum height for flex layouts
wrapMode
'none' | 'word' | 'char'
default:"'word'"
Text wrapping behavior

Events

TextareaRenderable doesn’t emit its own events by default, but you can use the onSubmit callback for form submissions.
const textarea = new TextareaRenderable(ctx, {
  x: 5,
  y: 5,
  width: 50,
  height: 10,
  onSubmit: (event) => {
    console.log("Form submitted with:", textarea.plainText)
  },
})

Methods

Text Operations

// Get plain text content
const text = textarea.plainText

// Set text content
textarea.setText("New content")

// Insert text at cursor
textarea.insertText("inserted text")

// Insert single character
textarea.insertChar("a")

Cursor Movement

// Move cursor
textarea.moveCursorLeft()
textarea.moveCursorRight()
textarea.moveCursorUp()
textarea.moveCursorDown()

// Move with selection
textarea.moveCursorLeft({ select: true })
textarea.moveCursorRight({ select: true })

// Word boundaries
textarea.moveWordForward()
textarea.moveWordBackward()
textarea.moveWordForward({ select: true })

// Line navigation
textarea.gotoLineHome()
textarea.gotoLineEnd()
textarea.gotoVisualLineHome()
textarea.gotoVisualLineEnd()

// Buffer navigation
textarea.gotoBufferHome()
textarea.gotoBufferEnd()

// Go to specific line
textarea.gotoLine(5)

Selection

// Select all text
textarea.selectAll()

// Get current cursor offset
const offset = textarea.cursorOffset

// Set cursor by offset
textarea.cursorOffset = 100

Deletion

// Delete characters
textarea.deleteChar() // Delete forward
textarea.deleteCharBackward() // Backspace

// Delete words
textarea.deleteWordForward()
textarea.deleteWordBackward()

// Delete line content
textarea.deleteLine() // Delete entire line
textarea.deleteToLineEnd() // Delete to end
textarea.deleteToLineStart() // Delete to start

Undo/Redo

textarea.undo()
textarea.redo()

Line Operations

// Insert newline
textarea.newLine()

Focus

textarea.focus()
textarea.blur()

Extmarks

Access the extmarks controller for advanced text highlighting and decorations.
const extmarks = textarea.extmarks
// Use extmarks API for custom highlighting

Keyboard Shortcuts

KeyAction
/ / / Move cursor
Ctrl+F / Ctrl+BMove cursor right/left
Home / EndGo to buffer start/end
Ctrl+A / Ctrl+EGo to line start/end
Meta+A / Meta+EGo to visual line start/end
Cmd+← / Cmd+→Go to visual line start/end (Kitty mode)
Cmd+↑ / Cmd+↓Go to buffer start/end (Kitty mode)
Meta+F / Meta+BMove word forward/backward
Ctrl+→ / Ctrl+←Move word forward/backward
Meta+→ / Meta+←Move word forward/backward

Selection

KeyAction
Shift+← / Shift+→ / Shift+↑ / Shift+↓Select while moving
Ctrl+Shift+A / Ctrl+Shift+ESelect to line start/end
Meta+Shift+A / Meta+Shift+ESelect to visual line start/end
Shift+Home / Shift+EndSelect to buffer start/end
Meta+Shift+F / Meta+Shift+BSelect word forward/backward
Cmd+ASelect all

Editing

KeyAction
BackspaceDelete character backward
Delete / Ctrl+DDelete character forward
Ctrl+W / Option+BackspaceDelete word backward
Meta+D / Meta+Delete / Ctrl+DeleteDelete word forward
Ctrl+Shift+DDelete line
Ctrl+KDelete to line end
Ctrl+UDelete to line start
EnterInsert newline
Meta+EnterSubmit (triggers onSubmit)

Undo/Redo

KeyAction
Ctrl+- / Cmd+ZUndo
Ctrl+. / Cmd+Shift+ZRedo

Examples

Notes Editor

import { Screen, TextareaRenderable, TextRenderable } from "@opentui/core"
import { fg } from "@opentui/core"

const screen = new Screen()
const ctx = screen.createContext()

const title = new TextRenderable(ctx, {
  x: 2,
  y: 2,
  text: "Notes",
  textColor: "#FFFF00",
})

const textarea = new TextareaRenderable(ctx, {
  x: 2,
  y: 4,
  width: 60,
  height: 20,
  backgroundColor: "#1a1a1a",
  focusedBackgroundColor: "#252525",
  placeholder: fg("#888888")("Start typing your notes..."),
})

const statusBar = new TextRenderable(ctx, {
  x: 2,
  y: 25,
  text: "Ctrl+S to save | Esc to exit",
  textColor: "#666666",
})

screen.append(title, textarea, statusBar)
textarea.focus()

Code Editor with Line Numbers

import { Screen, TextareaRenderable, TextRenderable } from "@opentui/core"

const screen = new Screen()
const ctx = screen.createContext()

const editor = new TextareaRenderable(ctx, {
  x: 5,
  y: 2,
  width: 70,
  height: 25,
  backgroundColor: "#0d1117",
  textColor: "#c9d1d9",
  focusedBackgroundColor: "#0d1117",
  initialValue: `function hello() {\n  console.log("Hello, world!")\n}`,
})

screen.append(editor)
editor.focus()

Chat Input with Submit

import { Screen, TextareaRenderable, TextRenderable } from "@opentui/core"

const screen = new Screen()
const ctx = screen.createContext()

const messageHistory = new TextRenderable(ctx, {
  x: 2,
  y: 2,
  width: 60,
  text: "",
})

const inputLabel = new TextRenderable(ctx, {
  x: 2,
  y: 20,
  text: "Message:",
})

const messageInput = new TextareaRenderable(ctx, {
  x: 2,
  y: 21,
  width: 60,
  height: 3,
  placeholder: "Type your message (Meta+Enter to send)...",
  backgroundColor: "#1a1a1a",
  onSubmit: () => {
    const message = messageInput.plainText
    if (message.trim()) {
      messageHistory.text += `\n> ${message}`
      messageInput.setText("")
    }
  },
})

screen.append(messageHistory, inputLabel, messageInput)
messageInput.focus()

Styled Placeholder

import { Screen, TextareaRenderable } from "@opentui/core"
import { fg, styled } from "@opentui/core"

const screen = new Screen()
const ctx = screen.createContext()

const textarea = new TextareaRenderable(ctx, {
  x: 5,
  y: 5,
  width: 50,
  height: 10,
  placeholder: [
    fg("#666666")("Type something... "),
    fg("#888888")("(supports markdown)"),
  ],
})

screen.append(textarea)
textarea.focus()

Advanced Features

Custom Key Bindings

const textarea = new TextareaRenderable(ctx, {
  x: 5,
  y: 5,
  width: 50,
  height: 10,
  keyBindings: [
    // Override default behavior
    { name: "s", ctrl: true, action: "select-all" },
    // Add custom save action
    { name: "s", super: true, action: "submit" },
  ],
})

Wrapping Modes

// No wrapping (scroll horizontally)
const noWrap = new TextareaRenderable(ctx, {
  x: 5,
  y: 5,
  width: 50,
  height: 10,
  wrapMode: "none",
})

// Word wrapping (default)
const wordWrap = new TextareaRenderable(ctx, {
  x: 5,
  y: 5,
  width: 50,
  height: 10,
  wrapMode: "word",
})

// Character wrapping
const charWrap = new TextareaRenderable(ctx, {
  x: 5,
  y: 5,
  width: 50,
  height: 10,
  wrapMode: "char",
})

Build docs developers (and LLMs) love