Textarea

Multi-line text input with cursor, selection, and rich keybindings.

Basic usage

Renderable API

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

const renderer = await createCliRenderer()

const textarea = new TextareaRenderable(renderer, {
  id: "notes",
  width: 50,
  height: 6,
  placeholder: "Type notes here...",
  backgroundColor: "#1a1a1a",
  focusedBackgroundColor: "#222222",
  textColor: "#FFFFFF",
  cursorColor: "#00FF88",
})

renderer.root.add(textarea)
textarea.focus()

Submit handling

Bind a submit action and listen for onSubmit:

import { TextareaRenderable } from "@opentui/core"

const textarea = new TextareaRenderable(renderer, {
  width: 50,
  height: 6,
  onSubmit: () => {
    console.log("Submitted:", textarea.plainText)
  },
  keyBindings: [{ name: "return", ctrl: true, action: "submit" }],
})

Placeholder styling

const textarea = new TextareaRenderable(renderer, {
  width: 40,
  height: 4,
  placeholder: "Type here",
  placeholderColor: "#666666",
})

Construct API

Not available yet. Use TextareaRenderable for now.

Properties

PropertyTypeDefaultDescription
widthnumber or string-Width in characters or percentage
heightnumber or string-Height in rows or percentage
initialValuestring""Initial text content
placeholderstring, StyledText, or nullnullPlaceholder content
placeholderColorstring or RGBA#666666Placeholder color
backgroundColorstring or RGBAtransparentBackground when unfocused
textColorstring or RGBA#FFFFFFText color when unfocused
focusedBackgroundColorstring or RGBAtransparentBackground when focused
focusedTextColorstring or RGBA#FFFFFFText color when focused
wrapMode"none", "char", or "word""word"Line wrapping mode
selectionBgstring or RGBA-Selection background
selectionFgstring or RGBA-Selection foreground
cursorColorstring or RGBA#FFFFFFCursor color
cursorStyleCursorStyleOptions-Cursor style and blinking
keyBindingsKeyBinding[]-Custom keybindings
keyAliasMapKeyAliasMap-Key alias mapping
onSubmit(event: SubmitEvent) => void-Submit handler
onContentChange(event: ContentChangeEvent) => void-Fired on content changes
onCursorChange(event: CursorChangeEvent) => void-Fired on cursor movement

Useful properties

PropertyTypeDescription
plainTextstringCurrent text content
cursorOffsetnumberCursor offset in the buffer
cursorCharacterOffsetnumber | undefinedOffset of the character under the cursor (skips trailing blank)
logicalCursor{ row, col }Logical line/column of the cursor
visualCursor{ row, col, visualLine }Visual (post-wrap) cursor position
traitsEditorTraitsEditor traits published to hosting UI (see Traits)

Cursor and selection control

TextareaRenderable (and its base EditBufferRenderable) exposes a programmatic API. You can move the cursor, edit text, and drive selections from your own keybindings or commands. All selection-aware movement methods accept { select: true } to extend the current selection instead of moving the cursor.

Cursor movement

textarea.setCursor(row, col)
textarea.moveCursorLeft()
textarea.moveCursorRight({ select: true })
textarea.moveCursorUp()
textarea.moveCursorDown()

textarea.moveWordForward({ select: true })
textarea.moveWordBackward()

textarea.gotoLine(0)
textarea.gotoLineStart()
textarea.gotoLineTextEnd()
textarea.gotoLineHome({ select: true }) // Emacs-style smart home
textarea.gotoLineEnd()
textarea.gotoVisualLineHome()
textarea.gotoVisualLineEnd()
textarea.gotoBufferHome()
textarea.gotoBufferEnd({ select: true })

Selection

textarea.setSelection(start, end) // half-open offsets
textarea.setSelectionInclusive(start, end) // inclusive end
textarea.selectAll()
textarea.clearSelection()
textarea.deleteSelection()

Editing

textarea.insertChar("a")
textarea.insertText("\ninserted")
textarea.deleteChar() // forward delete
textarea.deleteCharBackward() // backspace
textarea.deleteWordForward()
textarea.deleteWordBackward()
textarea.deleteToLineEnd()
textarea.deleteToLineStart()
textarea.deleteLine()
textarea.newLine()
textarea.undo()
textarea.redo()

These methods update the cursor, clear any active global selection, and call requestRender() for you.

Traits

The traits property lets an editor advertise intent to a host UI — which built-in keys it wants to capture, whether it wants the chrome to visually suspend, and a short status label for a footer or status bar. Assigning a new EditorTraits object emits the traits-changed event when the value differs from the previous one.

import { EditBufferRenderableEvents, type EditorTraits } from "@opentui/core"

textarea.traits = {
  capture: ["escape", "submit"], // consume these before host binds
  suspend: false,
  status: "Composing reply",
} satisfies EditorTraits

textarea.on(EditBufferRenderableEvents.TRAITS_CHANGED, (traits) => {
  updateFooter(traits.status ?? "")
})
FieldTypeDescription
captureEditorCapture[]Keys the editor wants to capture: "escape", "navigate", "submit", "tab"
suspendbooleanHint to the host to suspend ambient UI (dim borders, hide hints, etc.)
statusstringOptional short label surfacing editor mode in a status bar

Traits reset to an empty object when you destroy the renderable. Use isEditBufferRenderable(renderable) if you need to distinguish editor renderables from plain text renderables in a generic tree.