Skip to content
omaris

Data Display

Text

Text — the one component every string in the app goes through, instead of a <p>, a <span> or a <div> with a size class on it.

import { Text } from 'omaris'
Learn

Examples

Basic

variant is how it looks, as is what it means. Set both when they differ; leave one out and it is inferred — a heading tag picks its own role, and a variant on its own renders a paragraph.

Deployments

Every push to main builds and ships. The last ten are kept so you can roll back.

Updated 4 minutes ago
<script lang="ts">	import { Text } from 'omaris';</script>​<div class="flex max-w-md flex-col gap-2">	<Text as="h2">Deployments</Text>	<Text tone="muted">		Every push to <code>main</code> builds and ships. The last ten are kept so you can roll back.	</Text>	<Text variant="label-sm" tone="muted" class="mt-2">Updated 4 minutes ago</Text></div>

Scale

Five roles, three sizes each. The variant carries size, line height, letter spacing and weight together — if you find yourself adding font-semibold after it, the role is wrong, not the weight.

display-sm

The quick brown fox

headline-md

The quick brown fox

title-lg

The quick brown fox

body-md

The quick brown fox

label-md The quick brown fox
<script lang="ts">	import { Text } from 'omaris';</script>​<div class="flex w-full flex-col gap-4">	<div class="flex flex-col gap-1">		<Text variant="label-sm" tone="muted" font="mono">display-sm</Text>		<Text variant="display-sm">The quick brown fox</Text>	</div>	<div class="flex flex-col gap-1">		<Text variant="label-sm" tone="muted" font="mono">headline-md</Text>		<Text variant="headline-md">The quick brown fox</Text>	</div>	<div class="flex flex-col gap-1">		<Text variant="label-sm" tone="muted" font="mono">title-lg</Text>		<Text variant="title-lg">The quick brown fox</Text>	</div>	<div class="flex flex-col gap-1">		<Text variant="label-sm" tone="muted" font="mono">body-md</Text>		<Text variant="body-md">The quick brown fox</Text>	</div>	<div class="flex flex-col gap-1">		<Text variant="label-sm" tone="muted" font="mono">label-md</Text>		<Text variant="label-md">The quick brown fox</Text>	</div></div>

Tone and truncation

Colour is inherited by default, so Text stays legible on any surface. tone is for text that carries meaning of its own, and lines clamps to a fixed number with an ellipsis.

Inherits the surface

No tone needed here.

Card declined
lines={1}

A component library is a set of decisions someone already made, so that the next person does not have to make them again badly.

lines={2}

A component library is a set of decisions someone already made, so that the next person does not have to make them again badly.

<script lang="ts">	import { Text } from 'omaris';​	const NOTE =		'A component library is a set of decisions someone already made, so that the next person does not have to make them again badly.';</script>​<div class="flex w-72 max-w-full flex-col gap-4">	<div class="rounded-xl bg-primary p-3">		<Text variant="title-sm" class="text-primary-foreground">Inherits the surface</Text>		<Text variant="body-sm" class="text-primary-foreground/80">No tone needed here.</Text>	</div>​	<Text tone="destructive" variant="label-md">Card declined</Text>​	<div class="flex flex-col gap-1">		<Text variant="label-sm" tone="muted" font="mono">{'lines={1}'}</Text>		<Text lines={1}>{NOTE}</Text>		<Text variant="label-sm" tone="muted" font="mono">{'lines={2}'}</Text>		<Text lines={2}>{NOTE}</Text>	</div></div>

Numbers

tabular gives the digits a fixed width, so a column of figures lines up and a live counter stops twitching as it changes.

Revenue

48,210.00

Refunds

1,119.40

Net

47,090.60

<script lang="ts">	import { Text } from 'omaris';</script>​<div class="flex w-64 max-w-full flex-col gap-2">	<div class="flex items-baseline justify-between gap-4">		<Text variant="label-md" tone="muted">Revenue</Text>		<Text variant="title-sm" tabular>48,210.00</Text>	</div>	<div class="flex items-baseline justify-between gap-4">		<Text variant="label-md" tone="muted">Refunds</Text>		<Text variant="title-sm" tabular>1,119.40</Text>	</div>	<div class="flex items-baseline justify-between gap-4">		<Text variant="label-md" tone="muted">Net</Text>		<Text variant="title-sm" tabular>47,090.60</Text>	</div></div>

When to use it

Use it for

  • Every string in the app: a heading, a paragraph, a cell, a caption. variant is how it looks, as is what it means. <Text variant="title-md" as="h3"> is a card title that is also a heading.
  • Five roles, three sizes each. display-* for a stat card's hero number, headline-* for page and section titles, title-* for cards and dialogs, body-* for prose and cells, label-* for chips, headers and timestamps.
  • Text with its own meaning: tone="muted" for secondary text, tone="destructive" for an error. Everything else inherits, so text on a coloured surface stays legible.
  • Figures. tabular lines up a column and stops a live counter twitching; font="mono" for ids, hashes and anything compared character by character.
  • Clipping. lines={1} for a filename in a row, lines={2} for a card description.

Not for

  • A label inside a component that already sets its type, like a Button, Chip, Badge or Label → pass the string. The component owns the label-* role.
  • A block of code → Code Block. as="code" is for one identifier inside a sentence.
  • Long prose with its own headings, lists and links → the Typography guide covers that scale.
  • A sr-only span, a single glyph or a layout-only wrapper → a raw utility class. An emoji → Emoji from Emoji Picker.

Do

  • Let as carry the semantics and variant the look. Set both when they differ; leave one out and it is inferred. as="h2" is headline-md; a variant alone is a <p> (a <span> for label-*).
  • Pick the variant by the job of the text, not the size you want. Each variant sets size, line height, letter spacing and weight together. Needing font-semibold after variant="title-md" means the wrong variant.
  • Leave wrap alone. Headings balance and body avoids orphans already. Set wrap="nowrap" with lines={1} only for a cell that must stay one line.
  • On a dashboard card: display-sm is the metric, title-md the card's name, body-sm with tone="muted" the comparison under it.

Don't

  • Write <p class="text-sm text-muted-foreground">. That is <Text variant="body-sm" tone="muted">, and it moves with the theme.
  • Use weight to make a label bold. label-lg is already the weight buttons and tabs use.
  • Put tone="default" on text inside a tinted card or a filled button. It goes illegible in dark mode. Let it inherit.
  • Use display-lg twice on a screen. It is the one number the screen is about.

Quick reference

variant
  • display-lg
  • display-md
  • display-sm
  • headline-lg
  • headline-md
  • headline-sm
  • title-lg
  • title-md
  • title-sm
  • body-lg
  • body-md (default)
  • body-sm
  • label-lg
  • label-md
  • label-sm

Role and size — the type token minus text-. Pick by the job the text does: display is the one hero number on a screen, headline titles a page or section, title titles a card or dialog, body is prose and cell contents, label is buttons, chips, tabs and column headers.

tone
  • inherit (default)
  • default
  • muted
  • primary
  • secondary
  • tertiary
  • destructive
  • success
  • warning
  • info
  • inverse

Colour role. Inherits from the surface unless you say otherwise.

weight
  • normal
  • medium
  • semibold
  • bold

Overrides the weight the variant already carries. Rarely needed.

align
  • start
  • center
  • end
  • justify

Logical, so it follows the writing direction.

wrap
  • normal
  • balance
  • pretty
  • nowrap

Overrides the wrapping the variant sets.

lines
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Clamps to N lines with an ellipsis.

font
  • sans
  • mono

Family. Inherits unless set; Arabic swaps itself out already.

API

Text

Text — the one component every string in the app goes through, instead of a <p>, a <span> or a <div> with a size class on it.

Two independent decisions: variant is how it looks, as is what it means. <Text variant="title-md" as="h3"> is a card title that is also a real heading. Leave one out and it is inferred — as="h2" picks a headline, and a variant on its own renders a <p> (or a <span> for label-*, which is inline).

The variant is the whole type decision. Each one carries size, line height, letter spacing and weight from the token of the same name, so adding font-semibold after variant="title-md" means the role was wrong, not the weight. Long-form wrapping is set for you too: headings balance, body avoids orphans.

Colour is inherited by default, so a Text inside a coloured surface stays legible without being told. Ask for tone when the text itself carries meaning — muted for secondary copy, destructive for an error.

import { Text } from 'omaris'
<Text as="h1">Revenue</Text><Text variant="display-sm" tabular>$48,210</Text><Text tone="muted">Compared to last month.</Text><Text variant="label-sm" tone="muted" lines={1}>{file.name}</Text>

Props

variant
TextVariant

How it looks — the type token minus text-. Pick by the job the text does: display is the one hero number on a screen, headline titles a page or section, title titles a card or dialog, body is prose and cell contents, label is buttons, chips, tabs and column headers. Each one carries size, line height, letter spacing and weight together. Defaults to body-md, or to the role that matches as when that is a heading.

display-lg
The one number on a screen. Rare in a dashboard.
display-md
A hero figure that shares the screen with something else.
display-sm
The metric at the top of a card — the usual display size here.
headline-lg
Page titles.
headline-md
Section titles.
headline-sm
Sub-sections, dialog headings.
title-lg
Card titles.
title-md
Dialog titles, list group headers.
title-sm
Dense card titles, table captions.
body-lg
Lead paragraphs and long-form prose.
body-md
The default — descriptions, cell contents.
body-sm
Secondary copy, captions, help text.
label-lg
Buttons and tabs.
label-md
Chips, column headers, form labels.
label-sm
Overlines, timestamps, the text inside a badge.
as
TextElement

What it means. Defaults to span for label-* and p for everything else. Use a heading tag for anything that is one — the look does not make it a heading, this does.

tone

Defaults to 'inherit'

TextTone

Colour role. Inherits from the surface by default, so a Text inside a coloured container stays legible; set it when the colour itself means something — muted for secondary copy, destructive for an error.

inherit
Takes the colour of whatever it sits in.
default
The page's primary text colour, stated.
muted
Secondary copy — captions, hints, timestamps.
primary
secondary
tertiary
destructive
success
warning
info
inverse
For text on an inverted surface — a dark tooltip, an inverted toast.
weight
TextWeight

Overrides the weight the variant carries. If you want it, the role is probably wrong.

normal
medium
semibold
bold
align
TextAlign

Logical, so it follows the writing direction.

start
center
end
justify
wrap
TextWrap

Overrides the wrapping the variant sets — headings balance, body avoids orphans.

normal
Break wherever the line ends.
balance
Even line lengths — good for a heading of two or three lines.
pretty
No single-word last line. The default for `body-*`.
nowrap
One line, however long. Pair with `lines={1}` to clip it.
lines
TextLines

Clamps to N lines with an ellipsis. lines={1} is a single line.

1
2
3
4
5
6
font
TextFont

Family. Inherits unless set; mono for ids, hashes and code.

sans
mono
Ids, hashes, code, anything meant to be compared character by character.
tabular

Defaults to false

boolean

Fixed-width digits, for numbers that sit in a column.

for
string

Only with as="label": the id of the control it labels.

datetime
string

Only with as="time": the machine-readable date.

class
string
children
Snippet