Text

The text component draws bound text: a title, a subtitle, a body, a caption or a monospaced value. It is the most used component, and the Designer calls it Text. Use it for every line of words on a banner. It can hold several lines, and each line can have its own alignment and styled words. For a number in a pill use badge, and for a date use timestamp.

Minimal exampleJSON
{"type":"text","binding":"{title}","style":"title"}

Realistic example

A two-column header: the title on the left and a build tag in the accent colour on the right, then a body that allows Markdown links.

JSON
{"name":"text-demo","app":"example.bidbot","layoutVersion":2,"collapseEmpty":true,
 "grid":{"rows":2,"cols":2,"rowSizes":["auto","auto"],"colSizes":["fill","auto"],"gap":6,"padding":12,"width":380},
 "cells":[
  {"id":"title","row":0,"col":0,"component":{"type":"text","binding":"{title}","style":"title"}},
  {"id":"tag","row":0,"col":1,"align":"topTrailing",
   "component":{"type":"text","binding":"build {extra.build}","style":"caption","color":"accent","weight":"semibold"}},
  {"id":"body","row":1,"col":0,"colSpan":2,
   "component":{"type":"text","binding":"{body}","style":"body","markdown":true,"maxLines":4}}],
 "extra":{"build":"214"}}

In the picture below, look at the three lines of text: the bold title, the grey subtitle line and the body. Each is a text component, and the styles title, subtitle and body give them their size and colour.

Each line of text on the banner is a text component. The bold title uses the title style, the grey line the subtitle style and the last lines the body style.
A banner with a bold title, a grey subtitle line and two lines of body text

Each line of text on the banner is a text component. The bold title uses the title style, the grey line the subtitle style and the last lines the body style.

Properties

PropertyTypeDefaultDescription
typestringrequiredAlways "text".
bindingstringrequired unless lines is setThe text, with {token} placeholders. A binding with no token is literal text. It may hold line breaks and rich text markup.
linesarraynoneThe text as structured lines of styled runs. When set it takes precedence over binding. See Structured lines.
lineSpacingnumber0Extra points between lines. It must be 0 or more.
stylestringbodyA typography preset: title, subtitle, body, caption or mono.
maxLinesintegerper styleThe most lines to show, at least 1. When it is omitted the style decides.
colorstringper styleA hex colour, or accent, primary or secondary.
fontSizenumberper styleThe size in points, from 6 to 72.
weightstringper styleThe font weight: regular, medium, semibold or bold.
alignmentstringfollows the cellThe horizontal alignment of the lines: leading, center or trailing. A line's own align overrides it.
markdownbooleantrue for body, else falseWhether [text](url) links in the text are drawn as links.
emptyBehaviorstringtemplate defaultcollapse or keep. See Empty text.

Styles#

A style sets the font, the colour and how many lines show when you set none of your own.

StyleFontDefault colourDefault line limit
title13 pt semiboldprimary2
subtitle12 pt regularsecondary2
body12 pt regularprimaryThe banner's maxBodyLines, which is 8 unless the template or notification sets it.
caption10 pt regularsecondary1
mono11 pt monospacedprimary4

color, fontSize and weight replace the style's value for the whole component. A run in lines can replace them again for a few words.

Writing the binding#

The binding reads any token described in Bindings and tokens, which lists the standard fields, the fields a manifest declares, {extra.key} for the template's own values, and dotted names such as {customer.name} for nested metadata. Values print in a fixed way:

  • Numbers print without a trailing .0.
  • Booleans print as true or false.
  • Lists are joined with , .

In a binding that mixes tokens and text, an absent token becomes empty text and the literal text stays. The result is trimmed. "{sender}: {subject}" without a sender reads : Invoice. Prefer two components when the parts should disappear independently.

Rich text markup#

A binding, and the text of a run, can carry light markup. It works in every style. The Designer's text editor writes it for you.

WriteResult
A line break (\n in JSON)A new line.
**bold**Bold weight.
*italic*Italic.
`mono`A monospaced font.
__underline__An underline.
~~strike~~A strikethrough.
{{size=14 color=#FF3B30 font=serif weight=medium}}text{{/}}A span. Any of size (6 to 72), color (same values as color), font (sans, mono, serif, rounded) and weight can be given. {{/}} closes it.
{{align=center}} at the very start of a lineAligns that line: leading, center or trailing.
A backslash before *, _, ~, a backtick, { or another backslashThat character itself.
{token}A field, as everywhere else.

Rules for markup:

  • Markers combine (***both***, **{project}**) and can wrap tokens.
  • They never span a line break, and a span ends at the end of its line.
  • A marker with no partner, such as **oops, is shown as typed.
  • Values that arrive through tokens are never read as markup.
  • Markup has no links. Use markdown for [text](url).

validate_template warns about an unpaired marker, an unknown span key, a bad value, and {{align=...}} anywhere but the start of a line.

This binding writes a bold label on one line and an italic monospaced value, right-aligned, on the next:

JSON
{"type":"text","binding":"**Project:**\n{{align=trailing}}*`{project}`*","style":"body"}

Structured lines#

lines is the same model written out as data. Use it when an agent builds the text programmatically. Both forms compile to the same thing, and the Designer converts between them without loss.

JSON
{"type":"text","style":"body","lineSpacing":2,"lines":[
  {"runs":[{"text":"Project:","weight":"bold"}]},
  {"align":"trailing","runs":[{"token":"{project}","italic":true,"font":"mono","color":"accent"}]}]}
KeyOnDescription
alignlineleading, center or trailing. It overrides the component's alignment for this line.
runslineThe pieces of the line, drawn one after another.
textrunLiteral text. Markup is allowed. When a run has both text and token, the text comes first.
tokenrunA field written as "{project}".
weight, italic, font, size, color, underline, strikerunOverride the component's style, fontSize, weight and color for this run. A key you leave out is inherited.

Three rules apply to lines:

  • When lines is set, binding is ignored.
  • A run needs text or token.
  • A run size must be 6 to 72.

Empty text and line limits#

How empty lines are handled:

  • A line that contains tokens, all of them absent, is empty. It is dropped, or with emptyBehavior set to keep it stays as a blank line.
  • A line of literal text stays even when its neighbour is empty: "Project:\n{project}" without a project shows just Project:.
  • The component is empty when every line is, so "{count} new" with no count collapses instead of showing the word "new".
  • Blank lines at the top and bottom are trimmed, and a blank line in the middle is kept as spacing.

maxLines counts lines. Lines beyond the limit are cut off, and a line that wraps may use whatever the others leave. Clicking a banner whose text was cut shows all of it and the banner grows. A second click folds it back. The behaviour is described in How banners behave.

A long body is cut at its line limit.
A banner whose long body ends in an ellipsis at its line limit

A long body is cut at its line limit.

After one click the same banner shows the whole text.

A click on the banner lifts the line limits so the whole text is readable.
The same banner after a click, with the whole body shown

A click on the banner lifts the line limits so the whole text is readable.

Sizing and alignment#

  • In a fixed-width column the text wraps inside it.
  • In an auto column the column is as wide as the widest cell that sits in it alone, measured on one line, then trimmed to the space that is left. The widest columns are trimmed first.
  • In a fill column the text wraps at the column width.
  • The height is as many lines as the text needs, up to the line limit. A row is as tall as its tallest cell.
  • A text with its own alignment, or with a line that has an align, fills its cell's width and aligns inside it. A text without one hugs its content and the cell's align places it. "align":"topTrailing" puts the text at the top right and right-aligns its lines.
  • A kept empty text holds one invisible line, so its row keeps the height of a line.

Text has no action of its own. When markdown is on, a [text](url) link opens its URL. Three rules apply to links:

  • Only http, https and mailto links open. Any other scheme is blocked, and History records the click as a blocked link.
  • A click on a link never also triggers the banner's own click.

Common mistakes#

MistakeWhat happensFix
"binding":"title" with no braces.The banner shows the literal word "title".Write "{title}".
A wrong case in a key, such as maxlines.The key is ignored and the validator warns about an unknown key.Use the exact camel-case names.
A fontSize of 5 or 80.The validator reports an error.Stay between 6 and 72.
A [link](url) in a title.It is shown as typed.Set "markdown": true.
A literal * or _ pair in the text.It is read as markup.Write \* or \_.
{{align=center}} in the middle of a line.It is ignored and the validator warns.Put it first on the line.
A long title in an auto column.The column grows until the space runs out and squeezes its neighbours.Use a fill column and a maxLines.
Expecting a decimal to be rounded.It prints as sent, for example 3.5.Format the number in the app that sends it.

Edit this page on GitHub

Esc
Getting started
Guides