Colors
OpenTUI uses the RGBA class for color representation. The class stores colors as normalized float values (0.0-1.0) internally, but provides methods for working with different color formats.
Every color also carries a color tag that records the original intent: an RGB snapshot, an indexed ANSI slot, or the terminal default. The renderer uses this tag to keep palette-relative colors stable when the terminal palette changes.
Creating colors
From integers (0-255)
import { RGBA } from "@opentui/core"
const red = RGBA.fromInts(255, 0, 0, 255)
const semiTransparentBlue = RGBA.fromInts(0, 0, 255, 128)
From float values (0.0-1.0)
const green = RGBA.fromValues(0.0, 1.0, 0.0, 1.0)
const transparent = RGBA.fromValues(1.0, 1.0, 1.0, 0.5)
From hex strings
const purple = RGBA.fromHex("#800080")
const withAlpha = RGBA.fromHex("#FF000080") // Semi-transparent red
String colors
Most component properties accept both RGBA objects and color strings:
import { Text, Box } from "@opentui/core"
// Using hex strings
Text({ content: "Hello", fg: "#00FF00" })
// Using CSS color names
Box({ backgroundColor: "red", borderColor: "white" })
// Using RGBA objects
const customColor = RGBA.fromInts(100, 150, 200, 255)
Text({ content: "Custom", fg: customColor })
// Transparent
Box({ backgroundColor: "transparent" })
The parseColor utility
The parseColor() function converts various color formats to RGBA:
import { parseColor } from "@opentui/core"
const color1 = parseColor("#FF0000") // Hex
const color2 = parseColor("blue") // CSS color name
const color3 = parseColor("transparent") // Transparent
const color4 = parseColor(RGBA.fromInts(255, 0, 0, 255)) // Pass-through
Color intent
Every RGBA value stores a tag next to the RGBA snapshot to record the original color intent. The renderer reads this tag to decide which ANSI sequence to emit:
COLOR_TAG_RGB(256): a literal RGB color. The renderer emits38;2;r;g;b/48;2;r;g;b.COLOR_TAG_DEFAULT(257): the terminal’s default foreground or background. The renderer emits39/49(SGR default) so the terminal picks the right side of its palette.- Any integer in
0..255: an indexed ANSI color. The renderer emits38;5;n/48;5;nso the user’s theme overrides for that palette slot keep working when the palette changes.
Each color still carries its RGBA values so alpha blending and non-ANSI renderers work. The tag flows end-to-end through TypeScript, the FFI, the buffer, and the native renderer.
Default foreground and background
import { RGBA } from "@opentui/core"
// Will emit SGR 39 / 49 when rendered
const fg = RGBA.defaultForeground()
const bg = RGBA.defaultBackground()
You can pass an optional snapshot color to override the RGBA fallback. The renderer uses the snapshot for early frames, before it detects the terminal palette:
const fg = RGBA.defaultForeground("#E6EDF3")
Indexed ANSI colors (0-255)
import { RGBA, ansi256IndexToRgb } from "@opentui/core"
// Indexed colors keep their palette slot even if the user changes their theme
const ansiRed = RGBA.fromIndex(1)
const ansiBrightBlue = RGBA.fromIndex(12)
// With a custom RGBA snapshot (for early frames before palette detection)
const themed = RGBA.fromIndex(4, "#1F6FEB")
// Convert an ANSI 256 index to an RGB triplet
const [r, g, b] = ansi256IndexToRgb(196)
Inspecting and creating tagged colors
import { RGBA, decodeColorTag, COLOR_TAG_DEFAULT, COLOR_TAG_RGB } from "@opentui/core"
const fg = RGBA.defaultForeground()
RGBA.getIntentTag(fg) // => 257 (COLOR_TAG_DEFAULT)
decodeColorTag(fg.tag) // => { kind: "default" }
const indexed = RGBA.fromIndex(10)
decodeColorTag(indexed.tag) // => { kind: "indexed", index: 10 }
const literal = RGBA.fromHex("#00FF00")
decodeColorTag(literal.tag) // => { kind: "rgb" }
Exported tag constants and types
| Export | Description |
|---|---|
COLOR_TAG_RGB | 256 — marker for literal RGBA colors |
COLOR_TAG_DEFAULT | 257 — marker for terminal default foreground/background |
DEFAULT_FOREGROUND_RGB | [255, 255, 255] fallback RGB triplet for the default fg |
DEFAULT_BACKGROUND_RGB | [0, 0, 0] fallback RGB triplet for the default bg |
ColorKind | "rgb" | "indexed" | "default" |
RGBTriplet | readonly [number, number, number] |
ansi256IndexToRgb(index) | Converts an ANSI 256 palette index to an RGB triplet |
decodeColorTag(tag) | Returns the ColorKind (plus index for indexed) for a tag |
normalizeColorValue(v) | Parses a ColorInput and returns both the rgba and its tag |
Terminal palette detection
When the terminal supports it, the renderer queries the active palette (OSC 4 for palette slots, OSC 10/11 for default fg/bg) and publishes it to the native renderer. Indexed colors stay mapped to the terminal’s user-configured slots, and the renderer re-resolves RGB fallbacks against the detected palette.
const colors = await renderer.getPalette({ size: 256 })
console.log(colors.palette[1]) // '#cc0000' or whatever red your theme uses
console.log(colors.defaultForeground, colors.defaultBackground)
Useful members:
renderer.getPalette(options?)— returns aTerminalColorssnapshot. Cached by requested size (16or256).renderer.paletteDetectionStatus—"idle" | "detecting" | "cached".renderer.clearPaletteCache()— drop cached palettes (for example, after the user changes their theme).
getPalette throws if the renderer is suspended. The renderer also runs detection automatically on startup so the native side has palette data for 38;5 and 39/49 emission.
Alpha blending
You can use transparent cells and alpha blending for layered effects:
import { FrameBufferRenderable, RGBA } from "@opentui/core"
const canvas = new FrameBufferRenderable(renderer, {
id: "canvas",
width: 50,
height: 20,
})
// Draw with alpha blending
const semiTransparent = RGBA.fromValues(1.0, 0.0, 0.0, 0.5)
const transparent = RGBA.fromInts(0, 0, 0, 0)
canvas.frameBuffer.setCellWithAlphaBlending(10, 5, " ", transparent, semiTransparent)
Text attributes with colors
Combine colors with text attributes:
import { TextRenderable, TextAttributes, RGBA } from "@opentui/core"
const styledText = new TextRenderable(renderer, {
id: "styled",
content: "Important",
fg: RGBA.fromHex("#FFFF00"),
bg: RGBA.fromHex("#333333"),
attributes: TextAttributes.BOLD | TextAttributes.UNDERLINE,
})
Color constants
Common colors:
// Some examples of commonly used colors
const white = RGBA.fromInts(255, 255, 255, 255)
const black = RGBA.fromInts(0, 0, 0, 255)
const red = RGBA.fromInts(255, 0, 0, 255)
const green = RGBA.fromInts(0, 255, 0, 255)
const blue = RGBA.fromInts(0, 0, 255, 255)
const transparent = RGBA.fromInts(0, 0, 0, 0)