Skip to content

Typography ​

Two font stacks live on Neutral's semantic tokens.

--astryx-font-family-body and --astryx-font-family-heading start with Figtree, then -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, and sans-serif. --astryx-font-family-code starts with JetBrains Mono, then ui-monospace, SFMono-Regular, Menlo, Consolas, and monospace.

The theme package loads Figtree and JetBrains Mono at 400, 500, 600, 700, and 400 italic. Figtree also includes 600 italic. Importing a theme entry loads both faces.

Weight tokens are --astryx-font-weight-normal (400), medium (500), semibold (600), and bold (700). --astryx-font-weight-regular points at normal. Components already use that name. Upstream calls the token normal.

The type values on Text and Heading map to the --astryx-text-* sizes, weights, and line heights: display-1 through display-3, and body, large, label, code, and supporting. Display sizes use weight 400. Scale comes from size, not from bold.

Heading also takes level from 1 to 6, which renders h1 to h6 and sets that level's default size, weight, and line height. When the outline calls for an h2 at a different size, override it with type.

Font

Families, the size ramp, and weights. Sizes start at 14px and step by 1.2, then round.

--astryx-font-family-body

Figtree, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif

--astryx-font-family-heading

Figtree, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif

--astryx-font-family-code

ui-monospace, 'SF Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace

Starts with JetBrains Mono, then ui-monospace, SFMono-Regular, Menlo, Consolas, and monospace. The Neutral theme entry loads 400, 500, 600, 700, and 400 italic.

--astryx-font-size-4xs

0.375rem

--astryx-font-size-3xs

0.4375rem

--astryx-font-size-2xs

0.5rem

--astryx-font-size-xs

0.625rem

--astryx-font-size-sm

0.75rem

--astryx-font-size-base

0.875rem

--astryx-font-size-lg

1.0625rem

--astryx-font-size-xl

1.25rem

--astryx-font-size-2xl

1.5rem

--astryx-font-size-3xl

1.8125rem

--astryx-font-size-4xl

2.1875rem

--astryx-font-size-5xl

2.625rem

--astryx-font-weight-normal

400

--astryx-font-weight-regular

var(--astryx-font-weight-normal)

Components already use this name. It points at font-weight-normal, which is 400. Upstream calls that token normal.

--astryx-font-weight-medium

500

--astryx-font-weight-semibold

600

--astryx-font-weight-bold

700

Type roles

Headings, body, supporting text, and display roles. They point at the size and weight tokens above.

--astryx-text-heading-1-size

var(--astryx-font-size-2xl)

--astryx-text-heading-1-weight

var(--astryx-font-weight-semibold)

--astryx-text-heading-1-leading

1.3333

--astryx-text-heading-2-size

var(--astryx-font-size-xl)

--astryx-text-heading-2-weight

var(--astryx-font-weight-semibold)

--astryx-text-heading-2-leading

1.4

--astryx-text-heading-3-size

var(--astryx-font-size-lg)

--astryx-text-heading-3-weight

var(--astryx-font-weight-bold)

--astryx-text-heading-3-leading

1.4118

--astryx-text-heading-4-size

var(--astryx-font-size-base)

--astryx-text-heading-4-weight

var(--astryx-font-weight-bold)

--astryx-text-heading-4-leading

1.4286

--astryx-text-heading-5-size

var(--astryx-font-size-sm)

--astryx-text-heading-5-weight

var(--astryx-font-weight-semibold)

--astryx-text-heading-5-leading

1.6667

--astryx-text-heading-6-size

var(--astryx-font-size-xs)

--astryx-text-heading-6-weight

var(--astryx-font-weight-semibold)

--astryx-text-heading-6-leading

1.6

--astryx-text-body-size

var(--astryx-font-size-base)

--astryx-text-body-weight

var(--astryx-font-weight-normal)

--astryx-text-body-leading

1.4286

--astryx-text-large-size

var(--astryx-font-size-lg)

--astryx-text-large-weight

var(--astryx-font-weight-semibold)

--astryx-text-large-leading

1.4118

--astryx-text-label-size

var(--astryx-font-size-base)

--astryx-text-label-weight

var(--astryx-font-weight-medium)

--astryx-text-label-leading

1.4286

--astryx-text-code-size

var(--astryx-font-size-base)

--astryx-text-code-weight

var(--astryx-font-weight-normal)

--astryx-text-code-leading

1.4286

--astryx-text-supporting-size

var(--astryx-font-size-sm)

--astryx-text-supporting-weight

var(--astryx-font-weight-normal)

--astryx-text-supporting-leading

1.6667

--astryx-text-display-1-size

var(--astryx-font-size-5xl)

--astryx-text-display-1-weight

var(--astryx-font-weight-normal)

--astryx-text-display-1-leading

1.2381

--astryx-text-display-2-size

var(--astryx-font-size-4xl)

--astryx-text-display-2-weight

var(--astryx-font-weight-normal)

--astryx-text-display-2-leading

1.2571

--astryx-text-display-3-size

var(--astryx-font-size-3xl)

--astryx-text-display-3-weight

var(--astryx-font-weight-normal)

--astryx-text-display-3-leading

1.3793

Do and don't ​

Bigger is not better. One rule of thumb: body text is body, a page gets one display-1 through display-3, and everything else separates itself by level.

Do:

  • Use one display-* per page. A landing page hero and a key figure on a dashboard are the two places it earns its keep. Display weight is 400; the size carries the impact, not bold.
  • Pick level by outline. If the page runs h1 then h2 then h3, write that. When a size looks wrong, adjust type or weight on the spot; don't skip a level to get a size.
  • Put supporting text in supporting. Table notes, timestamps, and help text belong there: 12px instead of the body's 14px, in the secondary color.
  • Use type="code" on Text, or the Code component, for inline code. Both switch to the monospace stack.
  • Wrap headings with text-wrap="balance" and body text with text-wrap="pretty". The first evens out a two-line heading; the second avoids a lone word on the last line.
  • Pair long text with max-lines. A truncated Heading or Text shows the full string in a tooltip on hover.

Don't:

  • Don't use h4 as a small section heading. level 4 is the 14px bold eyebrow size, smaller than level 5. For a step down, use level="5", or give the h4 a type.
  • Don't express importance with size. Important things get weight, color, and position; size belongs to hierarchy.
  • Don't hand-write font-size and line-height. font-size: 18px drifts from the --astryx-text-* line height and weight, and a theme change leaves it misaligned.
  • Don't add letter-spacing to headings for style. On Chinese text it only looks loose.
  • Don't set long body copy in all caps. Eyebrows and labels are fine; sentences are hard work.
  • Don't mix more than three sizes in one block. If it needs more hierarchy, use a list or a subheading.