Paragraph¶
Body text. Identical to Title and Heading apart from its default font, its optional Width and its optional Height, which lets long text scroll within a fixed space.
{
"Type": "Paragraph",
"Text": "Pitch your tent on level ground, away from the river.",
"MarginLeft": 16
}
Text wraps to the available width automatically. A word too long to fit on a line by itself is broken across lines rather than left hanging off the edge, so item IDs and long compound words are safe.
Use \n for a deliberate line break, and \n\n for a blank line between paragraphs.
Paragraph fields¶
| Property | Type | Default | Description |
|---|---|---|---|
Width optional |
int? |
the available width | The width the paragraph occupies, in unscaled pixels × Scale. Text wraps at it and the paragraph reserves it. Clamped to the width available, so it can only narrow the paragraph and never widen it. |
Height optional |
int? |
as tall as its text | The height the paragraph occupies, in unscaled pixels × Scale. The paragraph reserves it whether or not its text fills it. Text that runs past the bottom is handled by Overflow. Clamped to the height left on the page. See Scrolling. |
Overflow optional |
string |
Scroll |
What happens to text that runs past Height. Scroll lets the reader scroll it into view and Truncate leaves it out. Ignored without a Height. |
ScrollBar optional |
ScrollBar |
the book's (a thin bar in the text color without one) | How the scroll bar looks. Replaces the book's ScrollBar whole when given. |
Give Width when you want a narrower column than the page provides, such as text set beside an image or a short line you want broken at a particular point.
{
"Type": "Paragraph",
"Text": "Pitch your tent on level ground, away from the river.",
"Width": 120,
"Alignment": "Center"
}
Width changes what Alignment aligns against
Without a Width a paragraph is only as wide as its longest line, so Alignment centres that block within the column. With a Width the paragraph is exactly that wide wherever the column allows it, so Alignment centres each line within the Width box and the box itself sits at the start of the column. Give the box an Alignment of its own by wrapping it in a Panel, or offset it with Position.
Scrolling¶
Give a paragraph a Height and it shows its text through a window that tall. When the text runs past the bottom, the reader can scroll through the rest:
- the mouse wheel, with the cursor over the paragraph
- the right stick on a controller, with the cursor over the paragraph
- the scroll bar down the paragraph's right side, by dragging its thumb or clicking above or below it to move a page at a time
{
"Type": "Paragraph",
"Text": "The legend speaks of a fish that only bites in the rain, deep in the mountain lake...",
"Height": 120
}
Text moves a whole line at a time, so a line is never cut in half at the edge of the window. The bar is only drawn while there is more text than fits, which is also the only time the text wraps short of it. A paragraph whose text fits keeps its full width and shows no bar.
Without a Width, a paragraph with text to scroll takes the full width available, so its bar sits at the edge of the column rather than just past its longest line.
Links scroll with their text
A link on a line scrolled out of view can't be hovered, clicked or stepped onto with a controller until it is scrolled back into view.
Typewriters keep their newest line in view
A typewriter in a scrolling paragraph scrolls it down to each new line as it types. Once the reader scrolls the paragraph themselves it stays where they put it. Clicking to finish the typing shows the rest of the text without moving the window.
The reader's place is kept when the book is refreshed, so a rebuild doesn't send them back to the top.
A paragraph with text to scroll counts as something worth stopping at for a controller, even without a tooltip or an action, so a reader on a controller can reach it to scroll it.
IgnoreCursor stops the reader scrolling
The mouse wheel, the right stick and a click on its bar all pass straight through a paragraph with IgnoreCursor, the same as the cursor does. A typewriter still scrolls it.
Leaving the rest out¶
Set Overflow to Truncate to show only the lines that fit, with no bar and nothing to scroll.
{
"Type": "Paragraph",
"Text": "A short note that only ever needs its first few lines shown.",
"Height": 60,
"Overflow": "Truncate"
}
Scroll bar¶
A flat bar in a single color. Every field is optional. The colors follow the paragraph's TextColor when left off, so the bar matches the page without being styled.
| Property | Type | Default | Description |
|---|---|---|---|
Width optional |
int |
6 |
How wide the bar is drawn, in unscaled pixels × Scale. |
Gap optional |
int |
6 |
The room left between the text and the bar, in unscaled pixels × Scale. |
Color optional |
color |
the text color, faint | The color of the thumb, the part that moves. |
HoverColor optional |
color |
see below | The thumb's color while the cursor is over the bar. Defaults to Color when that is given. Without one it is a stronger take on the text color. |
ActiveColor optional |
color |
HoverColor |
The thumb's color while it is being dragged. |
TrackColor optional |
color |
— | The color of the channel the thumb runs along. Left off, only the thumb is drawn. |
AutoHide optional |
bool |
false |
Whether the bar fades out while the reader leaves the text alone. See Hiding the bar. |
HideAfter optional |
number |
1.5 |
How long the bar stays up once left alone before it starts to fade, in seconds. Only used with AutoHide. |
{
"Type": "Paragraph",
"Text": "...",
"Height": 160,
"ScrollBar": {
"Width": 4,
"Color": "139 90 43 120",
"HoverColor": "139 90 43",
"TrackColor": "0 0 0 30"
}
}
The cursor reaches the bar through a strip at least 16 pixels wide down the paragraph's right side, so a thin bar is still easy to take hold of.
One bar for the whole book¶
Give the book a ScrollBar and every scrolling paragraph without one of its own takes it, so a book's bars can be styled once.
{
"Id": "you.CampingGuide",
"ScrollBar": {
"Color": "139 90 43 120",
"HoverColor": "139 90 43",
"AutoHide": true
},
"Pages": [ ... ]
}
A paragraph's own ScrollBar replaces the book's whole rather than adding to it, the same as an element's own link does. A paragraph that gives only a Width gets the default colors, not the book's, so copy across whatever it should keep.
Give HoverColor when you give Color
The default highlight is built from the text color, so once you choose the thumb's Color the bar no longer changes on hover until you choose a HoverColor too.
Hiding the bar¶
Set AutoHide to true and the bar fades out while the reader leaves the text alone, the way scroll bars do on a phone. It comes back:
- while the cursor is anywhere over the paragraph, links included
- whenever the text scrolls, whether by the wheel, the right stick, the bar or a typewriter following its newest line
Once the cursor leaves and the text stops moving, the bar waits HideAfter seconds and then fades. It also shows for that long the first time the paragraph appears, so the reader can see there is more to the text before it goes.
{
"Type": "Paragraph",
"Text": "...",
"Height": 160,
"ScrollBar": {
"AutoHide": true,
"HideAfter": 2
}
}
Tip
Leave AutoHide off when the reader might not think to look for more text. A hidden bar is the only sign a paragraph scrolls until the cursor reaches it.
Text fields¶
FontType defaults to Small, the game's small font.
| Property | Type | Default | Description |
|---|---|---|---|
Text optional |
string |
— | The text to draw. Wraps automatically to the available width, including breaking words that are too long for a line on their own. \n forces a line break. Can carry tokens, both Parchment's %Token% forms and the game's tokenizable strings. Leading whitespace is lost once the string also carries a Content Patcher {{ }} token (see Content Patcher tokens). Part of it can be colored with [color=...] markup (see inline color) given an effect such as [wave] (see text effects) or written in a language such as [dwarvish] (see languages), on every element but Input. On a Title, Heading or Paragraph it can also hold links. |
FontType optional |
font type |
varies | Which font to draw with. The default differs per element type. |
TextColor optional |
color |
the book's default | The text color. |
ShadowColor optional |
color |
the game's shadow color | The color of the drop shadow drawn behind the text, alpha included. Left off, the shadow follows TextColor's alpha instead. Ignored when FontType is SpriteText, which draws its own outline. |
Link fields¶
| Property | Type | Default | Description |
|---|---|---|---|
Links optional |
map of id to link |
— | The links this element's text points at with [link=id] markup. Ids are matched ignoring case. Checked before the book's shared links, and an entry here replaces the book's entry with the same id. |
Common fields¶
Scale on a Paragraph is the font scale, since a paragraph has no sprite. MarginLeft indents it, and because the margin narrows the width the text measures against, an indented paragraph wraps at the indented width rather than running off the page.
| Property | Type | Default | Description |
|---|---|---|---|
Type required |
element type |
— | Which kind of element this is. Determines every other field below. |
Id optional |
string |
— | An optional identifier for this element. Not used for navigation, purely for your own reference. |
Alignment optional |
Left | Center | Right |
Left |
Where the element sits within its container's width. Only has an effect when the element is narrower than the space available (see Layout). In a placed list it anchors the element and Position is measured from there. |
VerticalAlignment optional |
Top | Center | Bottom |
Top |
Where the element sits within its container's height. Only used in Background, Foreground, Underlay and Overlay, since a stacked element takes its vertical position from the elements above it (see Placed elements). Setting it on a stacked element logs an error and does nothing. |
Scale optional |
number |
1 |
The element's scale. Its meaning depends on the element type: sprite scale for Image, Panel, Banner, Button and Divider. Font scale for Title, Heading and Paragraph. See Units and scale. |
SpacingAfter optional |
int |
8 |
The gap between this element and the next one, in unscaled sprite pixels × Scale. Not applied after the last visible element, so a trailing gap can't appear at the bottom of a page or panel. |
MarginLeft optional |
int |
0 |
Space reserved to the element's left, in unscaled sprite pixels × Scale. This narrows the width the element measures against, so text wraps at the indented width rather than overflowing. |
MarginRight optional |
int |
0 |
Space reserved to the element's right, in unscaled sprite pixels × Scale. |
Position optional |
Point |
{ X: 0, Y: 0 } |
The element's position, in screen pixels. Only used in Background, Foreground, Underlay and Overlay, where elements are placed rather than stacked. Measured from wherever Alignment and VerticalAlignment anchor the element, so under the default Left and Top it's a plain coordinate (see Placed elements). Unlike every other spacing field this is not multiplied by Scale. Changing an element's scale resizes it in place rather than moving it. |
Condition optional |
string |
— | A game state query. When it evaluates false the element is hidden, and elements below it close the gap. Re-checked several times a second while the book is open. Understands tokens. |
Lifetime optional |
number |
— | Seconds the element stays up once shown. Setting it makes the element a timed one: hidden until a ShowElement action names it, so an Id is required. |
FadeAfter optional |
number |
— | Seconds before it starts fading, reaching nothing at the end of Lifetime. Needs Lifetime, and must be below it. |
IgnoreCursor optional |
bool |
false |
Lets the cursor pass straight through the element to whatever sits beneath it, so it can't be hovered or clicked. Its children and its own Background and Foreground are still reachable (see Passing the cursor through). |
Action optional |
string |
— | A trigger action run when the element is clicked. When set, the element becomes interactive: any element type can have one, not just Button. Understands tokens. |
Actions optional |
list of string |
— | Trigger actions run in order when the element is clicked. Combined with Action rather than replacing it, so an element with both runs Action first. Understands tokens. |
Sound optional |
string |
bigSelect |
The cue played when the element is clicked. Only used when Action or Actions is set, and played once however many actions run. Set to null for a silent click. |
HoverAction optional |
string |
— | A trigger action run when the cursor moves onto the element. Runs on entry, not while the cursor rests there. Sound doesn't apply. Understands tokens. |
HoverActions optional |
list of string |
— | Trigger actions run in order when the cursor moves onto the element. Combined with HoverAction rather than replacing it, so an element with both runs HoverAction first. Understands tokens. |
TypedAction optional |
string |
— | A trigger action run once every typewriter in the element's text has finished. See Typed actions. Understands tokens. |
TypedActions optional |
list of string |
— | Trigger actions run in order once the element's typewriters have finished. Combined with TypedAction rather than replacing it, so an element with both runs TypedAction first. |
DisplayName optional |
string |
— | The bold title of the element's hover tooltip. Works in every list, including a page's Background and Foreground. Can carry tokens. Any color, effect or link markup is taken out, as a tooltip draws plain text. |
Description optional |
string |
— | The body of the element's hover tooltip. Works in every list, including a page's Background and Foreground, where setting it is also what makes an otherwise decorative element reachable by the cursor. Ignored when IgnoreCursor is set, which logs a warning. Can carry tokens. Any color, effect or link markup is taken out, as a tooltip draws plain text. |
Tags optional |
list of string |
— | Free-form markers other mods can read off whatever the cursor is over, such as Lookup Anything support. Tagging an element also makes it reachable by the cursor, since a tag is only useful on something that can be hovered. Ignored when IgnoreCursor is set. See Tags. |
ParseTokenizableStrings optional |
bool |
true |
Whether the game's [Token] tokenizable strings are resolved in this element's Text, DisplayName, Description, Condition and actions. Set it to false where a square bracket is meant as the character itself. Color, effect and link markup is read either way. |
Long text can overflow the page
Nothing stops a paragraph from stacking past the bottom of a page. Parchment logs a warning, but you're responsible for fitting content to pages. Bear translations in mind: text that fits exactly in English may not in a longer language. Giving the paragraph a Height keeps it to a fixed space however long the text gets, with the rest a scroll away.