Paragraph
Every example on this page is live, drawn by the library's Storybook, where you can also change its props and see the result.
Body paragraph component with configurable size, weight, font family, style, truncation, and container fit behavior.
Import
import { Paragraph } from "~lib/typography";
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
children | ReactNode | Yes | N/A | Content to display |
size | "xs" | "sm" | "base" | "lg" | "xl" | No | "base" | Text size |
weight | "normal" | "medium" | "semibold" | "bold" | No | "normal" | Font weight |
font | "sans" | "serif" | "mono" | No | "sans" | Font family |
italic | boolean | No | false | Set the text in italic |
align | "left" | "center" | "right" | No | Inherited | Text alignment |
truncate | boolean | No | false | Truncate overflow with "…" |
lines | number | No | N/A | Show at most this many lines, ending in "…" |
fit | "content" | "fill" | "auto" | number | No | "content" | Container height behavior; auto also picks the size |
tokens | { pattern: RegExp; render?: (token) => node; variant?: "solid" | "outline" } | No | N/A | Draw marked words as bullets or icons |
emphasis | boolean | No | false | Draw **bold** and *italic* markdown |
flip | boolean | No | false | Turn the text upside down |
Examples
Default
Small Caption
Bold
Serif
font="serif" sets the text in a book serif, a second voice beside the sans for a punchline, an
answer or a sub-line. It reads at every size from xs up.
Italic
Set italic for text that is printed in italics, such as a card's flavor text or a deck's
description. It still clamps with lines and truncate.
Bold and Italic Words from Markdown
Text from an API often marks words with markdown, like **Fireball.** or *Dexterity*. Set
emphasis and those words are drawn bold or italic, without the asterisks. lines and truncate
count the text without its marks. One mark on each side (*word* or _word_) is italic, two are
bold, and three are both. A lone * between spaces is left as it is.
<Paragraph emphasis lines={3}>
**Fireball.** A bright streak flashes from your pointing finger and *blossoms*
into flame.
</Paragraph>
In an italic paragraph, an italic word is set upright so it still stands out. emphasis works
with tokens too.
Upside Down
Set flip to print text upside down, the way a puzzle page prints a riddle's answer. The text is
centered unless you give it an align. With lines, the answer still starts with its first word
and ends in "…" for someone who turns the frame around.
<Paragraph flip lines={2}>
A piano.
</Paragraph>
Aligned
Set align to center or right-align a paragraph. Leave it unset and the paragraph follows the
alignment of whatever it sits in.
Truncated
At Most a Few Lines
Set lines to cut text off with "…" after that many lines. The box is only as tall as the lines
it shows, so text that is shorter leaves no gap and whatever comes next moves up. A fixed fit
height, by contrast, keeps its full height even when the text is short.
Bullets and Icons in the Text
Some text names things riders know by a symbol, like the subway lines in "Uptown [4][5] trains are
delayed". Pass tokens with a pattern that finds them, and each one is drawn in the line: one or
two letters in a filled circle, longer names in a pill, and one of the Icon
short names, such as bus or train, as that icon. Tokens grow and shrink with size, never split across lines, and
still work with lines and truncate, so the "…" comes after a whole token. A screen reader reads
each token's text.
<Paragraph lines={2} tokens={{ pattern: /\[([^\]]+)\]/g }}>
Uptown [4][5] trains are delayed. Take the [bus] instead.
</Paragraph>
The part of the pattern inside ( ) is the token, so here [4] draws as a circle with 4 in it.
A pattern with no ( ) uses everything it matches.
Add variant: "outline" to draw each circle or pill as a ring with the letters inside, in place of
a filled one. It takes the same room as a filled one, so a line of text stays one line tall, and it
stays quiet beside a solid Badge, so a line-status board can mark every line and still let the
one status that matters stand out.
<Paragraph size="xs" tokens={{ pattern: /\[([^\]]+)\]/g, variant: "outline" }}>
[G] Delays
</Paragraph>
To draw some tokens your own way, such as with any other icon, add render. Return what to draw for
a token, or nothing to keep the usual drawing. An Icon you return without a size is sized to the
text for you. Keep what you draw about as
big as a circle, since it gets the same room.
import { Icon } from "~lib/icon";
<Paragraph
tokens={{
pattern: /\[([^\]]+)\]/g,
render: (token) =>
token === "shuttle bus icon" ? <Icon name="bus" /> : undefined,
}}
>
[shuttle bus icon] Shuttle buses replace [L] trains.
</Paragraph>;
Fit Modes
Fit Content (default)
Container sizes to its text content. Use when the text should take only as much space as it needs.
Fit Fill
Container fills available flex space. Use inside flex layouts when the text should expand to fill remaining space. Text that runs past that space is cut at the container's edge instead of drawn over the block below, which keeps a widget's saved render tidy when it is laid out in a smaller box than the one it was measured in.
Fit Auto
The container fills the room left, as fill does, and the paragraph picks its own size: it starts
at its size and steps down the type scale until its wrapped lines fit the box, measured in the
real font. A text that runs past even the smallest step is set at it and ends in "…". The size is
picked as the page renders, so a saved render keeps it.
<Paragraph size="xl" fit="auto">
{fact}
</Paragraph>
Fixed Height
Container has a hard-coded pixel height. Use when you need a precise, known container size.