Skip to main content

Overview

The Renderable class is the foundation for all UI components in OpenTUI. It provides layout management using Yoga (Flexbox), event handling, lifecycle management, and rendering capabilities.

Base Classes

BaseRenderable

The most basic renderable interface.
id
string
Unique identifier for the renderable
num
number
Internal numeric identifier (auto-assigned)
visible
boolean
Whether the renderable is visible
parent
BaseRenderable | null
Parent renderable (null for root)

Renderable

Extends BaseRenderable with full layout, styling, and event support.

Constructor

class Renderable extends BaseRenderable {
  constructor(ctx: RenderContext, options: RenderableOptions)
}
ctx
RenderContext
The renderer context (usually renderer)
options
RenderableOptions
Configuration options

Options

RenderableOptions

Configuration interface for creating renderables.

Layout Properties

width
number | 'auto' | `${number}%`
Width in cells, auto, or percentage
height
number | 'auto' | `${number}%`
Height in cells, auto, or percentage
flexGrow
number
Flex grow factor (Flexbox)
flexShrink
number
Flex shrink factor (Flexbox)
flexBasis
number | 'auto'
Flex basis (Flexbox)
flexDirection
'row' | 'column' | 'row-reverse' | 'column-reverse'
Flex direction (Flexbox)
flexWrap
'nowrap' | 'wrap' | 'wrap-reverse'
Flex wrap (Flexbox)
alignItems
'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'
Align items (Flexbox)
justifyContent
'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'
Justify content (Flexbox)
alignSelf
'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'
Align self (Flexbox)
position
'relative' | 'absolute'
Position type
overflow
'visible' | 'hidden' | 'scroll'
Overflow behavior
top
number | 'auto' | `${number}%`
Top position (for absolute positioning)
right
number | 'auto' | `${number}%`
Right position
bottom
number | 'auto' | `${number}%`
Bottom position
left
number | 'auto' | `${number}%`
Left position
minWidth
number | 'auto' | `${number}%`
Minimum width
minHeight
number | 'auto' | `${number}%`
Minimum height
maxWidth
number | 'auto' | `${number}%`
Maximum width
maxHeight
number | 'auto' | `${number}%`
Maximum height
margin
number | 'auto' | `${number}%`
Margin on all sides
marginX
number | 'auto' | `${number}%`
Horizontal margin (left and right)
marginY
number | 'auto' | `${number}%`
Vertical margin (top and bottom)
marginTop
number | 'auto' | `${number}%`
Top margin
marginRight
number | 'auto' | `${number}%`
Right margin
marginBottom
number | 'auto' | `${number}%`
Bottom margin
marginLeft
number | 'auto' | `${number}%`
Left margin
padding
number | `${number}%`
Padding on all sides
paddingX
number | `${number}%`
Horizontal padding
paddingY
number | `${number}%`
Vertical padding
paddingTop
number | `${number}%`
Top padding
paddingRight
number | `${number}%`
Right padding
paddingBottom
number | `${number}%`
Bottom padding
paddingLeft
number | `${number}%`
Left padding

Visual Properties

zIndex
number
Z-index for layering (higher values render on top)
visible
boolean
default:true
Whether the element is visible
opacity
number
Opacity (0 = transparent, 1 = opaque)

Behavior Properties

buffered
boolean
Use a frame buffer for rendering (performance optimization)
live
boolean
Keep the renderer running continuously

Hooks

renderBefore
(buffer: OptimizedBuffer, deltaTime: number) => void
Called before rendering this element
renderAfter
(buffer: OptimizedBuffer, deltaTime: number) => void
Called after rendering this element

Event Handlers

onMouse
(event: MouseEvent) => void
General mouse event handler (all mouse events)
onMouseDown
(event: MouseEvent) => void
Mouse button down event
onMouseUp
(event: MouseEvent) => void
Mouse button up event
onMouseMove
(event: MouseEvent) => void
Mouse move event
onMouseDrag
(event: MouseEvent) => void
Mouse drag event
onMouseDragEnd
(event: MouseEvent) => void
Mouse drag end event
onMouseDrop
(event: MouseEvent) => void
Mouse drop event
onMouseOver
(event: MouseEvent) => void
Mouse over event (hover)
onMouseOut
(event: MouseEvent) => void
Mouse out event (leave)
onMouseScroll
(event: MouseEvent) => void
Mouse scroll event
onKeyDown
(event: KeyEvent) => void
Key down event (when focused)
onPaste
(event: PasteEvent) => void
Paste event (when focused)
onSizeChange
() => void
Called when the element’s size changes

Properties

Position and Size

x
number
Absolute x position in the terminal
y
number
Absolute y position in the terminal
width
number
Computed width in cells
height
number
Computed height in cells
translateX
number
X translation offset
translateY
number
Y translation offset

State

visible
boolean
Visibility state (can be set to show/hide)
opacity
number
Opacity value (0-1)
zIndex
number
Z-index for rendering order
focusable
boolean
Whether the element can receive keyboard focus
focused
boolean
Whether the element currently has focus
live
boolean
Whether the element keeps the renderer running
isDestroyed
boolean
Whether the element has been destroyed

Context

ctx
RenderContext
The renderer context

Methods

Hierarchy Management

add()

Add a child element.
add(obj: Renderable | VNode | unknown, index?: number): number
obj
Renderable | VNode | unknown
Child element to add
index
number
Optional index to insert at
number
number
Index where the child was inserted (-1 if failed)

remove()

Remove a child element by ID.
remove(id: string): void
id
string
ID of the child to remove

insertBefore()

Insert a child before another child.
insertBefore(obj: Renderable | VNode | unknown, anchor: Renderable | unknown): number
obj
Renderable | VNode | unknown
Element to insert
anchor
Renderable | unknown
Anchor element to insert before
number
number
Index where the element was inserted

getChildren()

Get all children.
getChildren(): Renderable[]
Renderable[]
Renderable[]
Array of child elements

getChildrenCount()

Get the number of children.
getChildrenCount(): number
number
number
Number of children

getRenderable()

Get a child by ID.
getRenderable(id: string): Renderable | undefined
id
string
Child ID
Renderable | undefined
Renderable | undefined
The child element or undefined

findDescendantById()

Recursively find a descendant by ID.
findDescendantById(id: string): Renderable | undefined
id
string
Descendant ID
Renderable | undefined
Renderable | undefined
The descendant or undefined

Focus Management

focus()

Give keyboard focus to this element.
focus(): void

blur()

Remove keyboard focus from this element.
blur(): void

Rendering

requestRender()

Request a re-render.
requestRender(): void

Lifecycle

destroy()

Destroy this element and remove it from the hierarchy.
destroy(): void

destroyRecursively()

Destroy this element and all descendants.
destroyRecursively(): void

Layout

getLayoutNode()

Get the Yoga layout node.
getLayoutNode(): YogaNode
YogaNode
YogaNode
The Yoga layout node

Overridable Methods

These methods can be overridden in subclasses to customize behavior.

renderSelf()

Render the element itself (called during render pass).
protected renderSelf(buffer: OptimizedBuffer, deltaTime: number): void
buffer
OptimizedBuffer
Buffer to render to
deltaTime
number
Time since last render (in milliseconds)

onUpdate()

Called before rendering (for animations, state updates, etc.).
protected onUpdate(deltaTime: number): void
deltaTime
number
Time since last update

onResize()

Called when the element is resized.
protected onResize(width: number, height: number): void
width
number
New width
height
number
New height

onRemove()

Called when the element is removed from its parent.
protected onRemove(): void

destroySelf()

Called during destruction (for cleanup).
protected destroySelf(): void

onMouseEvent()

Called for mouse events (after event handlers).
protected onMouseEvent(event: MouseEvent): void
event
MouseEvent
The mouse event

handleKeyPress()

Called for key press events (when focused).
handleKeyPress?(key: KeyEvent): boolean
key
KeyEvent
The key event
boolean
boolean
Whether the event was handled

handlePaste()

Called for paste events (when focused).
handlePaste?(event: PasteEvent): void
event
PasteEvent
The paste event

Events

LayoutEvents

layout-changed

Emitted when layout changes.
renderable.on('layout-changed', () => {
  console.log('Layout changed')
})

resize

Emitted when the element is resized.
renderable.on('resize', () => {
  console.log('Element resized')
})

RenderableEvents

focused

Emitted when the element gains focus.
renderable.on('focused', () => {
  console.log('Element focused')
})

blurred

Emitted when the element loses focus.
renderable.on('blurred', () => {
  console.log('Element blurred')
})

Example

import { Renderable } from '@opentui/core'

class CustomButton extends Renderable {
  constructor(ctx: RenderContext, text: string) {
    super(ctx, {
      width: text.length + 4,
      height: 3,
      focusable: true,
    })
    
    this.text = text
  }
  
  protected renderSelf(buffer: OptimizedBuffer) {
    // Draw button background
    buffer.fillRect(0, 0, this.width, this.height, 
      RGBA.fromHex(this.focused ? '#0066cc' : '#004499'))
    
    // Draw button text
    const x = Math.floor((this.width - this.text.length) / 2)
    const y = Math.floor(this.height / 2)
    buffer.drawText(this.text, x, y, RGBA.fromHex('#ffffff'))
  }
  
  handleKeyPress(key: KeyEvent): boolean {
    if (key.name === 'enter' || key.name === 'space') {
      this.emit('click')
      return true
    }
    return false
  }
}

// Usage
const button = new CustomButton(renderer, 'Click Me')
button.on('click', () => console.log('Button clicked!'))
renderer.root.add(button)

Build docs developers (and LLMs) love