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
TextareaRenderablefor now.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
width | number or string | - | Width in characters or percentage |
height | number or string | - | Height in rows or percentage |
initialValue | string | "" | Initial text content |
placeholder | string, StyledText, or null | null | Placeholder content |
placeholderColor | string or RGBA | #666666 | Placeholder color |
backgroundColor | string or RGBA | transparent | Background when unfocused |
textColor | string or RGBA | #FFFFFF | Text color when unfocused |
focusedBackgroundColor | string or RGBA | transparent | Background when focused |
focusedTextColor | string or RGBA | #FFFFFF | Text color when focused |
wrapMode | "none", "char", or "word" | "word" | Line wrapping mode |
selectionBg | string or RGBA | - | Selection background |
selectionFg | string or RGBA | - | Selection foreground |
cursorColor | string or RGBA | #FFFFFF | Cursor color |
cursorStyle | CursorStyleOptions | - | Cursor style and blinking |
keyBindings | KeyBinding[] | - | Custom keybindings |
keyAliasMap | KeyAliasMap | - | 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
| Property | Type | Description |
|---|---|---|
plainText | string | Current text content |
cursorOffset | number | Cursor offset in the buffer |
cursorCharacterOffset | number | undefined | Offset 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 |
traits | EditorTraits | Editor 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 ?? "")
})
| Field | Type | Description |
|---|---|---|
capture | EditorCapture[] | Keys the editor wants to capture: "escape", "navigate", "submit", "tab" |
suspend | boolean | Hint to the host to suspend ambient UI (dim borders, hide hints, etc.) |
status | string | Optional 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.