design token

Text Styles

Predefined typography compositions for consistent text rendering across all components and frameworks.

Predefined typography compositions that bundle font size, weight, letter spacing, and line height into a single textStyle property.

Headings

One scale for every title. The large steps are expressive (tight tracking + leading) and fluid — heading.lg, heading.xl, and heading.2xl use a clamp() generated from the type scale, so they scale between 360px and 1280px viewports. heading.md is a fixed bold section title. The small steps (heading.sm–heading.3xs) are compact semibold headers for cards, banners, and dense components.

scale · headings
heading.2xlAa Bb 01 23
fontsanssizefluidweightboldleadingxtighttrackingtight
heading.xlAa Bb 01 23
fontsanssizefluidweightboldleadingxtighttrackingtight
heading.lgAa Bb 01 23
fontsanssizefluidweightboldleadingxtighttrackingtight
heading.mdAa Bb 01 23
fontsanssize2xlweightboldleadingsnugtrackingsnug
heading.smAa Bb 01 23
fontsanssizexlweightsemiboldleadingsnugtrackingnormal
heading.xsAa Bb 01 23
fontsanssizelgweightsemiboldleadingsnugtrackingnormal
heading.2xsAa Bb 01 23
fontsanssizemdweightsemiboldleadingsnugtrackingnormal
heading.3xsAa Bb 01 23
fontsanssizesmweightsemiboldleadingsnugtrackingnormal

Document headings

Bare <h1>–<h6> elements need no class: the preset’s global CSS maps each level to a descending step of this scale and colors them neutral.text.bold, so a lower level can never outrank a higher one.

global · headings
elementtext style
h1heading.lg
h2heading.md
h3heading.sm
h4heading.xs
h5heading.2xs
h6heading.3xs

heading.xl and heading.2xl are not mapped to an element — they are for hero and marketing headlines you style explicitly.

Body

lead is the intro paragraph under a heading. It is fluid like the large headings (a clamp() from md to lg, 16px → 20px across 360–1280px viewports) with relaxed leading and text-wrap: pretty.

scale · body
leadAa Bb 01 23
fontsanssizefluidweightnormalleadingrelaxedtrackingnormal
body.lgAa Bb 01 23
fontsanssizelgweightnormalleadingnormaltrackingnormal
body.mdAa Bb 01 23
fontsanssizemdweightnormalleadingnormaltrackingnormal
body.smAa Bb 01 23
fontsanssizesmweightnormalleadingnormaltrackingnormal

Labels

scale · labels
label.lgAa Bb 01 23
fontsanssizemdweightmediumleadingsnugtrackingnormal
label.mdAa Bb 01 23
fontsanssizesmweightmediumleadingsnugtrackingnormal
label.smAa Bb 01 23
fontsanssizexsweightmediumleadingsnugtrackingnormal

Numeric

Tabular figures for currency, counts, percentages, and KPIs. font-variant-numeric: tabular-nums keeps digits aligned and stops them jittering as values update, and lining-nums pins them to cap height in case the face ships oldstyle numerals by default.

numeric.xs is the small end of the set — body-sized figures that sit inline with UI text (table cells, pagination counts, timers, progress readouts) rather than headlining a card.

scale · numeric
numeric.lgAa Bb 01 23
fontsanssize4xlweightboldleadingxtighttrackingtighter
numeric.mdAa Bb 01 23
fontsanssize3xlweightboldleadingxtighttrackingtight
numeric.smAa Bb 01 23
fontsanssize2xlweightboldleadingxtighttrackingtight
numeric.xsAa Bb 01 23
fontsanssizesmweightmediumleadingsnugtrackingnormal

Control

Per-size typography for interactive labels (buttons, inputs, badges). These mirror the sizing pattern’s font scale and carry no weight of their own — each control keeps its own.

scale · control
control.xlAa Bb 01 23
fontsanssizelgweightinheritleadingnonetrackingnormal
control.lgAa Bb 01 23
fontsanssizemdweightinheritleadingnonetrackingnormal
control.mdAa Bb 01 23
fontsanssizesmweightinheritleadingnonetrackingnormal
control.smAa Bb 01 23
fontsanssizexsweightinheritleadingnonetrackingnormal
control.xsAa Bb 01 23
fontsanssizexsweightinheritleadingnonetrackingnormal

Special

quote is fluid too (md → lg, italic, relaxed leading). code is sized in em (0.9375em) so a snippet tracks whatever text hosts it.

scale · special
captionAa Bb 01 23
fontsanssizexsweightnormalleadingnormaltrackingnormal
eyebrowAa Bb 01 23
fontmonosizexsweightmediumleadingsnugtrackingwide
codeAa Bb 01 23
fontmonosize0.9375emweightnormalleadingsnugtrackingnormal
kbdAa Bb 01 23
fontmonosizexsweightmediumleadingnonetrackingnormal
quoteAa Bb 01 23
fontsanssizefluidweightnormalleadingrelaxedtrackingnormal

Usage

import { css } from "@pindoba/styled-system/css";

<h1 className={css({ textStyle: "heading.2xl" })}>Hero Heading</h1>
<h2 className={css({ textStyle: "heading.md" })}>Section Title</h2>
<p className={css({ textStyle: "body.md" })}>Paragraph text</p>
<strong className={css({ textStyle: "numeric.lg" })}>R$ 12,840.55</strong>
<label className={css({ textStyle: "label.md" })}>Form Label</label>
<code className={css({ textStyle: "code" })}>npm install</code>

Responsive text styles

heading.lg, heading.xl, heading.2xl, lead and quote are already fluid (clamp()), so they scale automatically. For discrete per-breakpoint steps you can also vary the token at the usage site:

<h1
  className={css({
    textStyle: { base: "heading.md", md: "heading.lg", lg: "heading.2xl" },
  })}
>
  Responsive heading
</h1>

Font size scale

Text styles are built on the fontSizes tokens, generated from one base (16px, the md step) and two ratios split at the base: steps at or below md use 1.14 (dense UI needs 12/14/16 granularity), steps above use 1.25 (display text needs presence).

TokenSizeStep
2xs10.8px1.14⁻³
xs12.31px1.14⁻²
sm14.04px1.14⁻¹
md16pxbase
lg20px1.25¹
xl25px1.25²
2xl31.25px1.25³
3xl39.06px1.25⁴
4xl48.83px1.25⁵
5xl61.04px1.25⁶

xs is the smallest size for running text and control labels; 2xs sits below the 12px legibility floor on purpose and is reserved for tiny secondary marks under or beside a larger label — a calendar day’s caption, a +N count.

Rhythm

Text styles pick a leading that suits the type, but that leading rarely lands on the 24px raster line. Add the data-rhythm attribute (or <Grid rhythm>) to a block and its text snaps to whole lines:

  • Line-height is quantised with round(up, 1em × ratio, 24px): body text asks for a ratio of 1.5 and headings 1.25, each rounded up to the next whole line, so text is never tighter than designed.
  • p, ul, ol, blockquote, figure, pre and table get a one-line trailing margin; h2 and h3 get two lines above.
  • The scope publishes --rhythm-line and --rhythm-half for recipes (through the rhythm pattern).

It is opt-in because quantising leading changes block heights; outside a [data-rhythm] scope nothing changes.

<article data-rhythm>
  <h2>Section</h2>
  <p>Every line of this paragraph sits on a 24px baseline.</p>
</article>

Best Practices

  • Use textStyle instead of setting fontSize, fontWeight, and lineHeight individually
  • Maintain hierarchy: heading > body > label > special
  • Reach for numeric.* for any prominent figure (currency, stats, counts) so digits stay tabular
  • The large headings are fluid out of the box; only reach for usage-site responsive steps when you need discrete jumps