---
title: "Text components"
---

> Documentation Index
> Fetch the complete documentation index at: https://aesthetic-docs.pages.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Text components

Build and read Minecraft text components — styled chat text with colors, clicks, hovers
and translations.

Constructors return a **text handle**. Builder methods style it in place and return it,
so calls chain:

```lua
local msg = text.empty()
:append(text.literal("[wiki] "):color("gold"))
:append(text.literal("diamond ore"):color(0x55FFFF):underlined()
    :open_url("https://minecraft.wiki/w/Diamond_Ore")
    :hover_text("Click to open the wiki"))
chat.print(msg)
```

Text handles are **snapshots**, not live handles. Wrapping game text
(`e:display_name()`, `item:tooltip()`) copies it; appending one handle to another
appends a copy. Later edits never leak into what was already built or shown.

`tostring(t)` gives the plain string. `..` concatenates handles/strings into a new
component.

## Constructors

| Function | What it builds |
|----------|----------------|
| `text.literal(s)` | Fixed text |
| `text.empty()` | Empty root — style children without the root style bleeding into them |
| `text.translatable(key, ...)` | Translatable key; extra args fill `%s` (strings, numbers, booleans or text handles) |
| `text.translatable_fallback(key, fb, ...)` | Like `translatable`, but shows `fb` when the key is missing |
| `text.keybind(key)` | Bound key for an action, e.g. `text.keybind("key.jump")` |
| `text.legacy(s, alt_char?)` | Parses `§`-coded string; pass `"&"` to also accept `&`-codes |
| `text.from_json(json)` | JSON text format (raises on invalid input) |

## Styling (chainable)

| Method | Effect |
|--------|--------|
| `:append(text_or_string)` | Appends a child component |
| `:color(c)` | Color: `0xRRGGBB`, a name like `"red"`, or `"#RRGGBB"` |
| `:shadow_color(argb)` | Shadow color, `0xAARRGGBB` |
| `:bold(b?)`, `:italic(b?)`, `:underlined(b?)` | Style flags; no arg means `true` |
| `:strikethrough(b?)`, `:obfuscated(b?)` | More flags (`obfuscated` = `§k`) |
| `:font(id)` | Font, e.g. `"minecraft:alt"` |
| `:insertion(s)` | Inserted into chat on shift-click |
| `:formatting(...)` | Formattings by name: `"red"`, `"bold"`, `"underline"`, `"reset"`, … |

## Click and hover

| Method | On click / hover |
|--------|------------------|
| `:run_command(cmd)` | Runs a command (include leading `/`) |
| `:suggest_command(cmd)` | Puts the command into the chat box |
| `:open_url(url)` | Opens a URL |
| `:copy_to_clipboard(s)` | Copies a string |
| `:change_page(n)` | Book page (only meaningful inside books) |
| `:hover_text(text_or_str)` | Text tooltip |
| `:hover_item(item)` | Item tooltip ([item handle](/item)) |
| `:hover_entity(entity)` | Entity tooltip ([entity handle](/entity)) |

Click and hover only work on text the game renders as chat (`chat.print`, real chat
lines). The HUD canvas draws plain strings — use `:string()` there.

## Reading

| Method | Returns |
|--------|---------|
| `:string()` | Plain string of the whole tree |
| `:truncated(n)` | Plain string capped at `n` characters |
| `:kind()` | `"literal"`, `"translatable"`, `"keybind"` or `"other"` |
| `:literal()` | Own literal string (no siblings), or `nil` |
| `:key()` | Translation key / keybind name, or `nil` |
| `:siblings()` | Child component snapshots |
| `:style()` | Own style table: `{color, color_name, shadow_color, bold, italic, underlined, strikethrough, obfuscated, insertion, font, click, hover}` |
| `:copy()` | Deep copy |
| `:to_json()` | JSON text format, or `nil` on failure |

Game text also comes as snapshots: `e:name_text()`, `e:display_name()`,
`e:custom_name()`; `item:name_text()`, `:formatted_name()`, `:hover_text()`,
`:tooltip()`; `name_text` on effect entries.

## Display

Pass a text handle (or plain string) to:

- [`chat.print(t)`](/chat) — local chat
- [`hud.actionbar(t)`](/hud) / [`hud.title(t)`](/hud) / [`hud.subtitle(t)`](/hud)

Server chat (`chat.say` / `chat.command`) is plain-string only.

```lua
local held = player:held_item()
for _, line in ipairs(held:tooltip()) do
print(line:string())
end

hud.actionbar(text.legacy("&6gold &r/ &b&laqua bold", "&"))
```

Source: https://aesthetic-docs.pages.dev/text/index.md
