Skip to content

Commit e9e7bc1

Browse files
authored
docs: document CSS-first typography for /next components (#4934)
* docs: document CSS-first typography for /next components Codify the convention adopted in #4660: components in /next set font-family, font-size, and line-height directly in their CSS using per-role semantic tokens (--eds-typography-ui-body-md-font-size etc.) rather than the runtime data-font-* attribute pattern. - typography.md: split into "Semantic typography tokens for component CSS" (preferred) and "Runtime data-attribute switching" (foundation / ad-hoc usage) - AGENTS.md: add "Typography in component CSS" subsection under the CSS guidelines with the token shape and a do/don't summary - ADR-0005: extend Decision to make the CSS-first principle explicit for font-family / font-size / line-height (not just font-weight) * docs: address review feedback on CSS-first typography docs - typography.md: update Best Practices and Output Formats to recommend per-role semantic tokens in component CSS, with data-font-* framed as the fallback for elements.css and ad-hoc markup - AGENTS.md: expand font-weight-* to font-weight-{lighter,normal,bolder} in the token shape so it is copy-paste ready - ADR-0005: move the font-family/font-size/line-height extension into its own subsection and promote text-box trimming to a sibling heading
1 parent 872a742 commit e9e7bc1

3 files changed

Lines changed: 59 additions & 5 deletions

File tree

AGENTS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,22 @@ For the underlying token system — colour categories, static vs dynamic tokens,
191191

192192
Prefer dynamic tokens (e.g. `--eds-selectable-space-vertical`, `--eds-typography-icon-size`) over hard-coded values. They adapt to density, typography, and accessibility settings without per-component overrides.
193193

194+
#### Typography in component CSS
195+
196+
Set `font-family`, `font-size`, and `line-height` directly in the component CSS using the per-role semantic typography tokens — do **not** add `data-font-family` / `data-font-size` / `data-line-height` attributes to the component's own elements:
197+
198+
```css
199+
.eds-button {
200+
font-family: var(--eds-typography-ui-body-font-family);
201+
font-size: var(--eds-typography-ui-body-md-font-size);
202+
line-height: var(--eds-typography-ui-body-md-line-height-squished);
203+
}
204+
```
205+
206+
Token shape: `--eds-typography-{ui-body|header}-{xs..6xl}-{font-size,line-height-default,line-height-squished,font-weight-{lighter,normal,bolder}}`. `font-family` is set once per role (`--eds-typography-{ui-body,header}-font-family`).
207+
208+
The `data-font-*` runtime-switching pattern still exists for `elements.css` defaults and ad-hoc consumer markup, but inside a component's own CSS the size and role are part of the design and should be expressed as tokens. See [`packages/eds-tokens/instructions/typography.md`](./packages/eds-tokens/instructions/typography.md) for both paths.
209+
194210
#### Pseudo-private custom properties
195211

196212
Define component-scoped variables with a `--_` prefix at the component root. Use these variables for all properties. In variants and states, **override only the variable — never the property directly**. The pattern was introduced for typography inheritance (see `documentation/adr/0005-typography-approach-for-eds-2.md`) and is now applied broadly across components.

documentation/adr/0005-typography-approach-for-eds-2.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ Inline elements (`strong`) consume `--_font-weight-bolder` via inheritance with
7676

7777
Utility classes `.eds-heading-bold` and `.eds-heading-light` work the same way, resolving to the correct weight for whatever heading level they are applied to.
7878

79+
### Extension: font-family, font-size, line-height
80+
81+
The same CSS-first principle extends beyond font-weight. Components in `/next` set `font-family`, `font-size`, and `line-height` directly in their CSS using per-role semantic tokens (`--eds-typography-ui-body-md-font-size` etc.). The `data-font-family` / `data-font-size` / `data-line-height` runtime-switching mechanism is reserved for `elements.css` defaults and ad-hoc consumer markup — a component's own elements should not carry these attributes, because the size and role are part of the component's design and are encoded in the token name. See [`packages/eds-tokens/instructions/typography.md`](../../packages/eds-tokens/instructions/typography.md) for both paths and the token shape.
82+
83+
### Text-box trimming
84+
7985
For text-box trimming, the `@supports` progressive enhancement pattern is used:
8086

8187
```css

packages/eds-tokens/instructions/typography.md

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,43 @@ applyTo: '**'
44

55
# Typography System
66

7-
This guide introduces the EDS typography system -- how typographic properties are tokenised, controlled via data attributes, and consumed in CSS and TypeScript.
7+
This guide introduces the EDS typography system -- how typographic properties are tokenised and consumed in CSS and TypeScript.
88

9-
## Core Concepts
9+
There are two ways to apply typography:
1010

11-
Typography in EDS is broken into five independent axes. Each axis has its own set of CSS variables and can be switched at runtime using a `data-*` attribute.
11+
1. **Static, per-element tokens (preferred for EDS 2.0 components in `/next`)** -- set `font-family`, `font-size`, and `line-height` directly in the component CSS using semantic tokens such as `--eds-typography-ui-body-md-font-size`. The size and family are part of the component's design; consumers do not switch them at runtime. See [Semantic typography tokens for component CSS](#semantic-typography-tokens-for-component-css).
12+
13+
2. **Runtime data-attribute switching** -- set `data-font-family` / `data-font-size` / `data-line-height` etc. on an element to flip the active typography axis at runtime. Useful for `elements.css` (semantic HTML defaults) and ad-hoc consumer markup, but not the default choice inside a component's own CSS. See [Runtime data-attribute switching](#runtime-data-attribute-switching).
14+
15+
If you are building a new component in `packages/eds-core-react/src/components/next/`, use approach 1. Approach 2 is documented for completeness and for cases where it is the right tool.
16+
17+
## Semantic typography tokens for component CSS
18+
19+
Components in `/next` use the per-size, per-role semantic tokens directly in their CSS:
20+
21+
```css
22+
.eds-button {
23+
font-family: var(--eds-typography-ui-body-font-family);
24+
font-size: var(--eds-typography-ui-body-md-font-size);
25+
line-height: var(--eds-typography-ui-body-md-line-height-squished);
26+
}
27+
```
28+
29+
The token shape is `--eds-typography-{role}-{size}-{property}` where:
30+
31+
- **role**: `ui-body` (UI / body copy, Inter) or `header` (headings, Equinor typeface)
32+
- **size**: `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`, `5xl`, `6xl`
33+
- **property**: `font-size`, `line-height-default`, `line-height-squished`, `font-weight-{lighter,normal,bolder}`
34+
35+
`font-family` is set once per role (`--eds-typography-{ui-body,header}-font-family`); it does not have a size segment.
36+
37+
Reach for these tokens whenever the component's typography is fixed by design -- which is the common case. Do not add `data-font-*` attributes to the component's own elements for this; the tokens above already encode the size + role combination.
38+
39+
For the underlying decision, including font-weight handling with `--_font-weight-{bolder,lighter}` for inline `strong`/`em` inheritance, see [ADR-0005: Typography approach for EDS 2.0](../../../documentation/adr/0005-typography-approach-for-eds-2.md).
40+
41+
## Runtime data-attribute switching
42+
43+
Typography in EDS is also broken into five independent axes. Each axis has its own set of generic CSS variables and can be switched at runtime using a `data-*` attribute. This is the mechanism that `elements.css` and other foundation-level styles use, and it is available for ad-hoc consumer markup.
1244

1345
| Axis | Data attribute | Modes |
1446
|------|---------------|-------|
@@ -166,12 +198,12 @@ The other axis files (`font-weight-*`, `line-height-*`, `tracking-*`) and the pe
166198

167199
| Format | Import path | Use case |
168200
|--------|-------------|----------|
169-
| **CSS variables** | `@equinor/eds-tokens/css/variables` | Standard web styling via data attributes |
201+
| **CSS variables** | `@equinor/eds-tokens/css/variables` | Component styling via per-role semantic tokens and runtime data-attribute switching |
170202
| **TypeScript matrix** | `@equinor/eds-tokens/ts/typography/font-family-{ui,header}` | Direct matrix access for non-CSS consumers (RN, SSR, design tooling) |
171203

172204
## Best Practices
173205

174-
- **Use data attributes** -- Let the token system resolve the right values rather than hardcoding
206+
- **Prefer per-role semantic tokens in component CSS** -- inside `/next` components, set `font-family`, `font-size`, and `line-height` directly with `--eds-typography-{role}-{size}-{property}` tokens; reach for `data-font-*` only for `elements.css` defaults and ad-hoc consumer markup
175207
- **Scale together** -- Font size, icon size, and gap are designed to work as a unit
176208
- **Combine axes freely** -- Each axis is independent; mix and match as needed
177209
- **Test across sizes** -- Verify layouts work at all font size modes

0 commit comments

Comments
 (0)