Skip to main content
OpenTUI provides a powerful styling system with RGBA colors, text attributes, and flexible color formats. This guide covers everything you need to create beautiful terminal UIs.

RGBA Color System

OpenTUI uses the RGBA class for consistent color representation. Colors are stored internally as normalized float values (0.0-1.0) for efficient processing.

Creating Colors

import { RGBA } from "@opentui/core"

const red = RGBA.fromInts(255, 0, 0, 255)
const semiTransparentBlue = RGBA.fromInts(0, 0, 255, 128)
const white = RGBA.fromInts(255, 255, 255, 255)

Using Colors

Colors can be applied to backgrounds, text, and borders:
import { BoxRenderable, TextRenderable, RGBA } from "@opentui/core"

const box = new BoxRenderable(renderer, {
  id: "styled-box",
  width: 30,
  height: 10,
  backgroundColor: RGBA.fromHex("#3b82f6"),
  borderColor: RGBA.fromInts(255, 255, 255, 255),
  borderStyle: "double",
})

const text = new TextRenderable(renderer, {
  id: "styled-text",
  content: "Hello, OpenTUI!",
  fg: "#FFFFFF", // Foreground (text color)
  bg: "#FF6B6B", // Background
})

Text Attributes

Text attributes control styling like bold, underline, and italic. They use bitwise OR to combine multiple attributes.

Available Attributes

import { TextAttributes } from "@opentui/core"

TextAttributes.BOLD        // Bold text
TextAttributes.DIM         // Dimmed/faint text
TextAttributes.ITALIC      // Italic text
TextAttributes.UNDERLINE   // Underlined text
TextAttributes.BLINK       // Blinking text (rarely supported)
TextAttributes.REVERSE     // Reverse video (swap fg/bg)
TextAttributes.HIDDEN      // Hidden text
TextAttributes.STRIKETHROUGH // Strikethrough text

Combining Attributes

Use bitwise OR (|) to combine multiple attributes:
import { TextRenderable, TextAttributes } from "@opentui/core"

const text = new TextRenderable(renderer, {
  id: "styled-text",
  content: "Important Message",
  fg: "#FFFF00",
  attributes: TextAttributes.BOLD | TextAttributes.UNDERLINE,
})

Styled Text with Template Literals

The t template literal and helper functions make it easy to create rich, styled text.

Basic Styling

import { TextRenderable, t, bold, underline, italic, fg, bg } from "@opentui/core"

const styledText = t`This is ${bold("bold")}, ${underline("underlined")}, and ${italic("italic")} text.`

const coloredText = t`${fg("#FF0000")("Red text")} and ${bg("#00FF00")(fg("#000000")("black on green"))}`

const text = new TextRenderable(renderer, {
  id: "rich-text",
  content: styledText,
})

Color Helpers

import { t, red, green, blue, yellow } from "@opentui/core"

const text = t`
${red("ERROR:"))} Connection failed
${green("SUCCESS:")} Data loaded
${yellow("WARNING:")} Low memory
${blue("INFO:")} Update available
`

Dynamic Content

Template literals support dynamic values and expressions:
import { t, bold, green, red, fg } from "@opentui/core"

let counter = 0
let cpuLoad = 45.2
let isOnline = true

const statusText = t`
${bold("System Status:")}
Counter: ${green(counter)}
CPU Load: ${cpuLoad > 80 ? red(`${cpuLoad}%`) : green(`${cpuLoad}%`)}
Connection: ${isOnline ? green(bold("ONLINE")) : red(bold("OFFLINE"))}
Random ID: ${fg("#E67E22")(Math.floor(Math.random() * 9999))}
`

Box Styling

Boxes support backgrounds, borders, and various border styles.

Border Styles

const box = new BoxRenderable(renderer, {
  borderStyle: "single",
  border: true,
})
// ┌─────┐
// │     │
// └─────┘

Complete Box Styling

import { BoxRenderable, TextRenderable, RGBA } from "@opentui/core"

const styledBox = new BoxRenderable(renderer, {
  id: "settings-panel",
  width: 40,
  height: 15,
  backgroundColor: RGBA.fromHex("#1a1a2e"),
  borderStyle: "double",
  borderColor: "#00FFFF",
  title: "Settings",
  titleAlignment: "center",
  border: true,
  padding: 1,
})

const content = new TextRenderable(renderer, {
  id: "settings-content",
  content: "Panel content here...",
  fg: "#FFFFFF",
})

styledBox.add(content)

Transparency and Alpha Blending

OpenTUI supports alpha transparency for creating layered UIs.

Creating Transparent Elements

import { BoxRenderable, RGBA } from "@opentui/core"

// Semi-transparent overlay
const overlay = new BoxRenderable(renderer, {
  id: "overlay",
  position: "absolute",
  left: 0,
  top: 0,
  width: "100%",
  height: "100%",
  backgroundColor: RGBA.fromValues(0.0, 0.0, 0.0, 0.7), // 70% opacity
  zIndex: 100,
})

// Frosted glass effect
const dialog = new BoxRenderable(renderer, {
  id: "dialog",
  width: 50,
  height: 20,
  backgroundColor: RGBA.fromValues(0.1, 0.1, 0.1, 0.9),
  borderColor: RGBA.fromValues(1.0, 1.0, 1.0, 0.3),
  borderStyle: "rounded",
  zIndex: 101,
})

FrameBuffer with Alpha

For custom rendering with transparency:
import { FrameBufferRenderable, RGBA } from "@opentui/core"

const canvas = new FrameBufferRenderable(renderer, {
  id: "canvas",
  width: 60,
  height: 30,
  respectAlpha: true, // Enable alpha blending
})

// Draw with transparency
const transparentRed = RGBA.fromValues(1.0, 0.0, 0.0, 0.5)
canvas.frameBuffer.fillRect(10, 5, 20, 10, transparentRed)

Theme Integration

React to terminal theme changes:
import { createCliRenderer, type ThemeMode } from "@opentui/core"

const renderer = await createCliRenderer()

// Check current theme
const currentTheme = renderer.themeMode // "dark", "light", or null

// Listen for theme changes
renderer.on("theme_mode", (mode: ThemeMode) => {
  console.log("Theme changed to:", mode)
  
  if (mode === "dark") {
    // Apply dark theme colors
    renderer.setBackgroundColor("#001122")
  } else if (mode === "light") {
    // Apply light theme colors
    renderer.setBackgroundColor("#F5F5F5")
  }
})

Color Palettes

Create consistent color schemes:
import { RGBA } from "@opentui/core"

const palette = {
  background: RGBA.fromHex("#001122"),
  primary: RGBA.fromHex("#3b82f6"),
  secondary: RGBA.fromHex("#8b5cf6"),
  success: RGBA.fromHex("#10b981"),
  warning: RGBA.fromHex("#f59e0b"),
  error: RGBA.fromHex("#ef4444"),
  text: RGBA.fromHex("#ffffff"),
  textMuted: RGBA.fromHex("#9ca3af"),
}

// Use throughout your app
const successBox = new BoxRenderable(renderer, {
  backgroundColor: palette.success,
  borderColor: palette.text,
})

Performance Tips

Create RGBA objects once and reuse them instead of creating new ones frequently:
// Good
const blue = RGBA.fromHex("#0000FF")
box1.backgroundColor = blue
box2.backgroundColor = blue

// Avoid
box1.backgroundColor = RGBA.fromHex("#0000FF")
box2.backgroundColor = RGBA.fromHex("#0000FF")
Update styled text only when values change:
let lastValue = 0

renderer.setFrameCallback(async () => {
  const newValue = Math.floor(Math.random() * 100)
  if (newValue !== lastValue) {
    statusText.content = t`Value: ${green(newValue)}`
    lastValue = newValue
  }
})
String colors are parsed once and cached:
// Both are fine, string is more concise
const box1 = new BoxRenderable(renderer, {
  backgroundColor: "#3b82f6",
})

const box2 = new BoxRenderable(renderer, {
  backgroundColor: RGBA.fromHex("#3b82f6"),
})

Examples

Status Dashboard

import { TextRenderable, t, bold, green, red, fg, bg } from "@opentui/core"

const cpuLoad = 72.5
const memoryUsage = 85.2
const isOnline = true

const dashboard = t`
${bold("System Stats:")}
${fg("#FF6B6B")("CPU:"))} ${cpuLoad > 80 ? red(bold(`${cpuLoad}%`)) : green(`${cpuLoad}%`)}
${fg("#4ECDC4")("Memory:")} ${memoryUsage > 90 ? red(bold(`${memoryUsage}%`)) : fg("#FFA500")(`${memoryUsage}%`)}
${fg("#FFE66D")("Status:")} ${isOnline ? green(bold("ONLINE")) : red(bold("OFFLINE"))}
${bg("#FFFF00")(fg("#000000")(bold(" NOTICE "))))} System update available
`

const statusDisplay = new TextRenderable(renderer, {
  id: "dashboard",
  content: dashboard,
})

Styled Panel

import { BoxRenderable, TextRenderable, RGBA, t, bold, fg } from "@opentui/core"

const panel = new BoxRenderable(renderer, {
  id: "info-panel",
  width: 50,
  height: 15,
  backgroundColor: RGBA.fromValues(0.1, 0.1, 0.2, 0.95),
  borderStyle: "rounded",
  borderColor: "#00FFFF",
  title: "Information",
  titleAlignment: "center",
  border: true,
  padding: 1,
})

const content = new TextRenderable(renderer, {
  id: "panel-content",
  content: t`
${bold(fg("#00FFFF")("Welcome to OpenTUI"))}

This is a ${fg("#FF6B6B")("styled")} panel with:
${fg("#00FF00")("Custom colors")}
${fg("#FFE66D")("Transparency")}
${fg("#9B59B6")("Rounded borders")}
  `,
})

panel.add(content)

Next Steps

Keyboard and Mouse

Handle user input events

Animations

Animate colors and properties

Build docs developers (and LLMs) love