These docs describe the main branch, including unreleased changes. Read the 0.6.0 docs.

Text

Text displays styled text with colors, attributes, and selection. Use it for labels and prose. Use Code or Markdown for parsed rich content.

Availability#

Field Availability
Package @opentui/core
Core renderable TextRenderable
React <text> (automatic)
Solid <text> (automatic)
Status Built in

Basic usage#

Renderable API#

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

const renderer = await createCliRenderer()

const text = new TextRenderable(renderer, {
  id: "greeting",
  content: "Hello, OpenTUI!",
  fg: "#00FF00",
})

renderer.root.add(text)

Text attributes#

Combine text attributes with bitwise OR:

import { TextRenderable, TextAttributes } from "@opentui/core"

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

You can also apply bold, italic, and underline separately:

Available attributes#

Attribute Description
TextAttributes.BOLD Bold text
TextAttributes.DIM Dimmed text
TextAttributes.ITALIC Italic text
TextAttributes.UNDERLINE Underlined text
TextAttributes.BLINK Blinking text
TextAttributes.INVERSE Inverted colors
TextAttributes.HIDDEN Hidden text
TextAttributes.STRIKETHROUGH Strikethrough text

Template literals for rich text#

Use the t template tag to style parts of one text element:

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

const richText = new TextRenderable(renderer, {
  id: "rich",
  content: t`${bold("Important:")} ${fg("#FF0000")(underline("Warning!"))} Normal text`,
})

Available style functions#

import { t, bold, dim, italic, underline, blink, reverse, strikethrough, fg, bg } from "@opentui/core"

// Basic attributes
t`${bold("bold text")}`
t`${italic("italic text")}`
t`${underline("underlined")}`
t`${strikethrough("deleted")}`

// Colors
t`${fg("#FF0000")("red text")}`
t`${bg("#0000FF")("blue background")}`

// Combining styles
t`${bold(fg("#FFFF00")("bold yellow"))}`

React and Solid can compose inline <span>, <b>, <strong>, <i>, <em>, <u>, <br>, and <a href> elements inside <text>. They are text-only children. They cannot mount directly under a Box or another layout element. See inline text elements for availability.

Positioning#

const text = new TextRenderable(renderer, {
  id: "positioned",
  content: "Absolute position",
  position: "absolute",
  left: 10,
  top: 5,
})

Align lines#

textAlign pads each rendered line inside the text width. The pad for one line does not depend on the longest line.

const text = new TextRenderable(renderer, {
  content: "hi\nworld",
  width: 10,
  height: 2,
  textAlign: "center",
})

"left" is the default. "center" and "right" use leftover columns in the text width. A line that already fills the text width does not move.

Set a width, or let a parent stretch the text. Alignment has no effect when every line already fills the text width.

Wrapping runs first. Then textAlign pads each rendered line.

Change textAlign after mount with text.textAlign = "right". CodeRenderable inherits the same option.

textAlign does not replace Yoga box alignment.

Text selection#

Text selection lets users copy text. It is on by default:

const selectableText = new TextRenderable(renderer, {
  id: "selectable",
  content: "Select me!",
  selectable: true, // Default is true
})

const nonSelectable = new TextRenderable(renderer, {
  id: "label",
  content: "Button Label",
  selectable: false, // Disable selection
})

Properties#

Property Type Default Description
content string | StyledText "" The text content to display
fg string | RGBA #FFFFFF Foreground (text) color
bg string | RGBA transparent Background color
attributes TextAttributes 0 Text styling attributes
selectable boolean true Whether users can select the text
wrapMode "none" | "char" | "word" "word" Line wrapping mode
textAlign "left" | "center" | "right" "left" Per-line alignment within the text width
position "relative" | "absolute" "relative" Positioning mode
left, top, right, bottom number | "auto" | "{number}%" - Position offsets

Example: status bar#

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

const statusBar = new BoxRenderable(renderer, {
  position: "absolute",
  bottom: 0,
  width: "100%",
  height: 1,
  backgroundColor: "#333333",
  flexDirection: "row",
  justifyContent: "space-between",
  paddingLeft: 1,
  paddingRight: 1,
})
statusBar.add(
  new TextRenderable(renderer, {
    content: t`${bold("myfile.ts")} - ${fg("#888888")("TypeScript")}`,
  }),
)
statusBar.add(
  new TextRenderable(renderer, {
    content: t`Ln ${fg("#00FF00")("42")}, Col ${fg("#00FF00")("15")}`,
  }),
)

renderer.root.add(statusBar)

Read Text and terminal cells for graphemes, wrapping, alignment, and display-cell widths. See Colors, Layout, and Interaction, focus, and selection for shared behavior. Use Box to lay out text with other components.

Changes0.6.0, 0.5.12, 0.5.3
0.6.0
native: A width change in word-wrap mode releases the layout memory of a narrower wrap. Before this fix, a 94 KiB text wrapped at width 1 and then at width 80 kept about 46 MB. (#1602)
Added TextRenderable.destroyOwnedResources, TextRenderable.requestRender, TextRenderable.nativeIntegration.
Removed TextRenderable.destroy, TextRenderable.onLifecyclePass.
0.5.12
core: textAlign aligns each line of a text renderable to "left", "center", or "right". It works with wrapMode set to "char" or "word". Alignment applies after wrapping. TextBufferView.setTextAlign() sets it on a view. (#1507)
0.5.3
core: Fixes an abort when a width-1 glyph is drawn at column -1. The renderer now clips a glyph whose range ends at or before column 0, and it no longer reads past the cell buffer. (#1361)