Skip to main content

Design system components

Text

Body and inline typography with size and line-height tokens.

Status: stable. Group: display. Markdown version: /design-system/components/text.md

When to use

Text owns body and inline typography: paragraphs by default, with a polymorphic as prop for span, strong, em, cite, div and the heading tags when you need a heading shape at body weight. It shares the size and lineHeight ladder with Title, so editorial rhythm stays consistent across the site.

When not to use

  • Do not nest a <Text as="p"> inside another <p>. HTML rejects nested paragraphs; use as="span" for inline positions.
  • Do not override font-size via inline style. The ladder is the contract; drift in consumer code is invisible until someone audits typography.
  • Do not use Text for section headings; headings carry outline semantics Text does not, use Title.

Look-alikes

  • Display: Do not stack Display lines to fake a type ladder; hierarchy below the hero belongs to Title and Text.
  • HelperText: Do not label form fields with Text; use Label (htmlFor) and HelperText (aria-describedby).
  • Label: Do not label form fields with Text; use Label (htmlFor) and HelperText (aria-describedby).
  • Title: Do not use Text for section headings; headings carry outline semantics Text does not, use Title.

Props

Text props
PropTypeDefaultDescriptionRequired
childrenReact.ReactNode | ReactI18NextChildren | Iterable<ReactI18NextChildren>noneNo description in the contract.Yes
as"div" | "cite" | "em" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "strong"pNo description in the contract.No
size"xl" | "xs" | "s" | "xxs" | "m" | "l" | "xxl"mNo description in the contract.No
lineHeight"normal" | "tight" | "snug" | "relaxed" | "loose"noneNo description in the contract.No
flushbooleanfalseDrop the block margins. Use when the parent owns spacing: a row, a cell, a card or a flex/grid gap.No

Variants

  • Available sizes: xxs, xs, s, m, l, xl, xxl (default m).
  • Allowed as values: div, cite, em, h1, h2, h3, h4, h5, h6, p, span, strong (default p).
  • Allowed lineHeight values: normal, tight, snug, relaxed, loose.

Invalid combinations

The contract records no invalid combinations.

Keyboard

The contract records no keyboard interaction.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

Text rules
LevelRuleHow it is checked
MUSTARIA: Semantic element via as prop.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Manual review, last on 2026-11-04.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-04.
SHOULDDefault to the p element for body copy; switch to as=span for inline positions so paragraphs never nest.Not stated in the contract.
SHOULDSet a lede with size=l and lineHeight=snug directly under a hero Title.Not stated in the contract.
SHOULDUse as=strong or as=em for inline emphasis so screen readers announce the semantics.Not stated in the contract.
SHOULDUse size=xs for captions and metadata.Not stated in the contract.
SHOULD NOTDo not label form fields with Text; use Label (htmlFor) and HelperText (aria-describedby).Not stated in the contract.
SHOULD NOTDo not render code with Text; CodeSnippet and CodeBlockWindow own the monospace ramp.Not stated in the contract.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { Text } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/typography exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.
  • Also available as the custom element <dt-text>; see the custom elements manifest.