Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

text

One paragraph drawn in the fonts chain or a named family: labels, clocks, notification bodies. It sizes to its content, wraps and elides inside a bounded width, and mixes bold, italic, colour and links through runs. For typing, use a textfield.

Two notification cards. In the first, the title elides and the body wraps to two lines, eliding the second; the second card’s short texts fit.

local function card(icon_name, title, body)
    return row {
        width = "Fill",
        padding = 12,
        spacing = 10,
        radius = 12,
        background = "#313244",
        children = {
            icon { name = icon_name, size = 32, foreground = "#CDD6F4", align_v = "Center" },
            column { width = "Fill", align_v = "Center", spacing = 2, children = {
                text { content = title, width = "Fill", font_size = 14, elide = "End" },
                text { content = body, width = "Fill", foreground = "#A6ADC8",
                       wrap = "Word", max_lines = 2, elide = "End" },
            } },
        },
    }
end

return column { width = 340, spacing = 8, children = {
    card("dialog-information-symbolic", "Firmware update ready for the USB-C dock",
        "3 packages can be installed. Restart to finish the kernel upgrade and load the new graphics driver."),
    card("battery-caution-symbolic", "Battery low", "12% left"),
} }

The middle column is "Fill" so the texts have a bounded width; the icon keeps its 32 px.

Properties

text takes the common properties, plus:

PropertyTypeDefaultBehaviour
contentstring|TextRun[]|Bound""A string, or an array of up to 10000 runs, drawn as one paragraph
fontstring|BoundThe fonts chainFamily placed before the fonts chain. "" raises; an unknown family falls back to the chain
font_sizenumber|Bound, [1, 8192]12Each line is 1.2 × font_size tall
foregroundColor|Bound"#FFFFFF"A colour; a run’s color overrides it
text_align"Start"|"Center"|"End"|Bound"Start"Aligns lines inside the node’s own box; Start/End follow each line’s reading direction. Matters only when the box is wider than the text
wrap"None"|"Word"|Bound"None""Word" breaks at words, mid-word when one word is too wide. Needs a bounded width (width, "Fill" or a stretched cross axis)
max_linesnumber|Bound0Line cap under wrap = "Word"; 0 is unlimited, a negative value is refused. Ignored without wrap
elide"None"|"End"|Bound"None""End" ends an over-long line with an ellipsis; under wrap it applies to the last kept line
on_linkfun(href: string)NoneClick on a run with an href; the engine never opens it. Takes the click from any ancestor button; plain text passes it through

Runs

Each run in a content array is a table:

FieldValuesDefaultBehaviour
textStringRequiredA run without it is refused; an empty one is skipped
bold, italicBooleanfalseUses the family’s bold or italic face when one exists
underlineBooleanfalseUnderline in the run’s colour
colorColourThe node’s foreground
hrefStringNoneHanded to on_link on click; the pointer shows "pointer" over it. "" is no link

A run also takes kind = "text", so a notification body’s text spans pass through unchanged. Drop its image spans, which have no text. A nil hole ends the array.

local body = text {
    width = 280,
    wrap = "Word",
    content = {
        { text = "Update ready. " },
        { text = "3 packages", bold = true },
        { text = " can be installed. " },
        { text = "Release notes", underline = true, color = "#89B4FA", href = "https://example.org/notes" },
    },
    on_link = function(href) process.detach("xdg-open", { href }) end,
}

Size

A text node measures its content: one line per paragraph line, 1.2 × font_size each, as wide as the widest line. wrap and elide need a box narrower than the text, so give the node a width, "Fill", or a stretched cross axis (a text in a fixed-width column wraps at the column’s width). In a content-sized row, the text measures one line and overflows instead.

How do I…

TaskAnswer
Truncate a long titlewidth (or "Fill") plus elide = "End"
Show at most two lineswrap = "Word", max_lines = 2, elide = "End" and a bounded width, as in the card
Bold one wordA run with bold = true
Make a clickable linkA run with href plus on_link on the node (process.detach to open it)
Use an icon font glyphfont = "Symbols Nerd Font" (any installed family) with the glyph as content
Centre text in a fixed-width boxtext_align = "Center" with a width
Show a live valueBind content to a signal: content = volume:map(function(v) return v and tostring(v) or "" end)

Gotchas

TrapFix
A wrap = "Word" text runs off the edge on one lineWrapping needs a bounded width: set width, "Fill", or put it in a fixed-width column. A content-sized row offers none
elide = "End" never ellipsizesSame cause: the box is as wide as the text. Bound the width
max_lines has no effectIt applies only under wrap = "Word"
text_align = "Center" does nothingThe box is exactly as wide as the text. Give it a width, or centre the node with align_h
font = "" raisesOmit font to use the chain
A link run is not clickableLinks need on_link on the same text; without it the click goes to the button around it
content = 42 raisescontent takes a string or runs: tostring(n)

See also: textfield, fonts, icon.

Source: vocabulary, content parsers, measure, line height, link hit testing.