Skip to content
Merged
36 changes: 19 additions & 17 deletions packages/theme/docs/ds-tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,22 @@ Do not edit directly.

### Typography

| Variable name | Description |
| ---------------------------------- | ----------------------- |
| `--wpds-font-family-heading` | Headings font family |
| `--wpds-font-family-body` | Body font family |
| `--wpds-font-family-mono` | Monospace font family |
| `--wpds-font-size-x-small` | Extra small font size |
| `--wpds-font-size-small` | Small font size |
| `--wpds-font-size-medium` | Medium font size |
| `--wpds-font-size-large` | Large font size |
| `--wpds-font-size-x-large` | Extra large font size |
| `--wpds-font-size-2x-large` | 2X large font size |
| `--wpds-font-line-height-x-small` | Extra small line height |
| `--wpds-font-line-height-small` | Small line height |
| `--wpds-font-line-height-medium` | Medium line height |
| `--wpds-font-line-height-large` | Large line height |
| `--wpds-font-line-height-x-large` | Extra large line height |
| `--wpds-font-line-height-2x-large` | 2X large line height |
| Variable name | Description |
| ----------------------------- | -------------------------------------------- |
| `--wpds-font-family-heading` | Headings font family |
| `--wpds-font-family-body` | Body font family |
| `--wpds-font-family-mono` | Monospace font family |
| `--wpds-font-size-xs` | Extra small font size |
| `--wpds-font-size-sm` | Small font size |
| `--wpds-font-size-md` | Medium font size |
| `--wpds-font-size-lg` | Large font size |
| `--wpds-font-size-xl` | Extra large font size |
| `--wpds-font-size-2xl` | 2X large font size |
| `--wpds-font-line-height-xs` | Extra small line height |
| `--wpds-font-line-height-sm` | Small line height |
| `--wpds-font-line-height-md` | Medium line height |
| `--wpds-font-line-height-lg` | Large line height |
| `--wpds-font-line-height-xl` | Extra large line height |
| `--wpds-font-line-height-2xl` | 2X large line height |
| `--wpds-font-weight-regular` | Regular font weight for body text |
| `--wpds-font-weight-medium` | Medium font weight for emphasis and headings |

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It occurs to me that we call this "medium", where in other sizing tokens we use "md" abbreviated t-shirt size naming. Maybe we're okay with this seeming inconsistency? There's not an obvious abbreviated form to represent all the options here (i.e. "regular").

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm ok with font weight tokens not to be abbreviated

26 changes: 14 additions & 12 deletions packages/theme/src/prebuilt/css/design-tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,20 @@
--wpds-font-family-heading: -apple-system, system-ui, 'Segoe UI', 'Roboto',
'Oxygen-Sans', 'Ubuntu', 'Cantarell', 'Helvetica Neue', sans-serif; /* Headings font family */
--wpds-font-family-mono: 'Menlo', 'Consolas', monaco, monospace; /* Monospace font family */
--wpds-font-line-height-2x-large: 40px; /* 2X large line height */
--wpds-font-line-height-large: 28px; /* Large line height */
--wpds-font-line-height-medium: 24px; /* Medium line height */
--wpds-font-line-height-small: 20px; /* Small line height */
--wpds-font-line-height-x-large: 32px; /* Extra large line height */
--wpds-font-line-height-x-small: 16px; /* Extra small line height */
--wpds-font-size-2x-large: 32px; /* 2X large font size */
--wpds-font-size-large: 15px; /* Large font size */
--wpds-font-size-medium: 13px; /* Medium font size */
--wpds-font-size-small: 12px; /* Small font size */
--wpds-font-size-x-large: 20px; /* Extra large font size */
--wpds-font-size-x-small: 11px; /* Extra small font size */
--wpds-font-line-height-2xl: 40px; /* 2X large line height */
--wpds-font-line-height-lg: 28px; /* Large line height */
--wpds-font-line-height-md: 24px; /* Medium line height */
--wpds-font-line-height-sm: 20px; /* Small line height */
--wpds-font-line-height-xl: 32px; /* Extra large line height */
--wpds-font-line-height-xs: 16px; /* Extra small line height */
--wpds-font-size-2xl: 32px; /* 2X large font size */
--wpds-font-size-lg: 15px; /* Large font size */
--wpds-font-size-md: 13px; /* Medium font size */
--wpds-font-size-sm: 12px; /* Small font size */
--wpds-font-size-xl: 20px; /* Extra large font size */
--wpds-font-size-xs: 11px; /* Extra small font size */
--wpds-font-weight-medium: 499; /* Medium font weight for emphasis and headings */
--wpds-font-weight-regular: 400; /* Regular font weight for body text */
}

[data-wpds-theme-provider-id][data-wpds-density='default'] {
Expand Down
26 changes: 14 additions & 12 deletions packages/theme/src/prebuilt/js/design-tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,18 @@ export default [
'--wpds-font-family-heading',
'--wpds-font-family-body',
'--wpds-font-family-mono',
'--wpds-font-size-x-small',
'--wpds-font-size-small',
'--wpds-font-size-medium',
'--wpds-font-size-large',
'--wpds-font-size-x-large',
'--wpds-font-size-2x-large',
'--wpds-font-line-height-x-small',
'--wpds-font-line-height-small',
'--wpds-font-line-height-medium',
'--wpds-font-line-height-large',
'--wpds-font-line-height-x-large',
'--wpds-font-line-height-2x-large',
'--wpds-font-size-xs',
'--wpds-font-size-sm',
'--wpds-font-size-md',
'--wpds-font-size-lg',
'--wpds-font-size-xl',
'--wpds-font-size-2xl',
'--wpds-font-line-height-xs',
'--wpds-font-line-height-sm',
'--wpds-font-line-height-md',
'--wpds-font-line-height-lg',
'--wpds-font-line-height-xl',
'--wpds-font-line-height-2xl',
'--wpds-font-weight-regular',
'--wpds-font-weight-medium',
];
54 changes: 54 additions & 0 deletions packages/theme/src/prebuilt/ts/token-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,57 @@ export type InteractiveStrokeColor =
| 'brand'
| 'error'
| 'error-strong';

/**
* Foreground color variants for text elements.
*/
export type ForegroundColor =
| 'neutral'
| 'neutral-weak'
| 'success'
| 'success-weak'
| 'info'
| 'info-weak'
| 'warning'
| 'warning-weak'
| 'caution'
| 'caution-weak'
| 'error'
| 'error-weak'
| 'neutral-active'
| 'neutral-disabled'
| 'neutral-strong'
| 'neutral-strong-active'
| 'neutral-strong-disabled'
| 'neutral-weak-disabled'
| 'brand'
| 'brand-active'
| 'brand-disabled'
| 'brand-strong'
| 'brand-strong-active'
| 'brand-strong-disabled'
| 'error-active'
| 'error-disabled'
| 'error-strong'
| 'error-strong-active'
| 'error-strong-disabled';

/**
* Font family variants.
*/
export type FontFamily = 'heading' | 'body' | 'mono';

/**
* Font size scale.
*/
export type FontSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';

/**
* Font weight variants.
*/
export type FontWeight = 'regular' | 'medium';

/**
* Line height scale.
*/
export type LineHeight = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
31 changes: 31 additions & 0 deletions packages/theme/terrazzo.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,37 @@ export default defineConfig( {
},
],
},
{
name: 'ForegroundColor',
description: 'Foreground color variants for text elements.',
patterns: [
{
pattern: /^wpds-color\.fg\.[^.]+\.(.+)$/,
transform: ( variant ) =>
variant.split( '.' ).join( '-' ),
},
],
},
{
name: 'FontFamily',
description: 'Font family variants.',
patterns: [ /^wpds-font\.family\.([^.]+)$/ ],
},
{
name: 'FontSize',
description: 'Font size scale.',
patterns: [ /^wpds-font\.size\.([^.]+)$/ ],
},
{
name: 'FontWeight',
description: 'Font weight variants.',
patterns: [ /^wpds-font\.weight\.([^.]+)$/ ],
},
{
name: 'LineHeight',
description: 'Line height scale.',
patterns: [ /^wpds-font\.line-height\.([^.]+)$/ ],
},
],
} ),
pluginModeOverrides(),
Expand Down
37 changes: 24 additions & 13 deletions packages/theme/tokens/typography.json

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like type or typography would be a better name for this group of tokens — font feels specific to some aspects (family, weight, size, style, face....) but not to all (line height, letter spacing, etc)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, it's a good question. I could have sworn I took inspiration from this somewhere in how the file and top-level grouping was named, but the examples I could find in either the spec or examples in Terrazzo documentation either don't mention it, or do group them as "typography".

@aduth aduth Dec 30, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think how I may have been considering it was reserving "typography" as a grouping for the compositions of individual font token values, similar to how it's documented in the specification with "$type": "typography" composing "base/text" values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. In my mind, I still think that "type" or "typography" is a better name for this group, and it seems to match how terrazzo and others' approach too (colors, typography, spacing...).

That doesn't mean that we can not have $type: "typography" (what the spec that you linked above calls a "Typography component").

In fact, it poses the question of how we should structure those "presets" — are they semantic tokens, or an even higer-level entity?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jameskoster out of curiosity, do you foresee the need for more tokens in the future (targeting things like letter spacing or other metrics)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe 😄 Difficult to say at this stage. I don't think letter-spacing is used in the existing componentry.

Original file line number Diff line number Diff line change
Expand Up @@ -37,57 +37,68 @@
},
"size": {
"$type": "dimension",
"x-small": {
"xs": {
"$value": { "value": 11, "unit": "px" },
"$description": "Extra small font size"
},
"small": {
"sm": {
"$value": { "value": 12, "unit": "px" },
"$description": "Small font size"
},
"medium": {
"md": {
"$value": { "value": 13, "unit": "px" },
"$description": "Medium font size"
},
"large": {
"lg": {
"$value": { "value": 15, "unit": "px" },
"$description": "Large font size"
},
"x-large": {
"xl": {
"$value": { "value": 20, "unit": "px" },
"$description": "Extra large font size"
},
"2x-large": {
"2xl": {
"$value": { "value": 32, "unit": "px" },
"$description": "2X large font size"
}
},
"lineHeight": {
"line-height": {

@ciampo ciampo Dec 23, 2025 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker for now, but have we considered which unit to use to express these tokens? Using px, at least initially, makes sense as a way to ensure continuity with previous variables, but I'd like to understand if other alternatives are completely off the table (most typically, rem for sizes, and unitless for line heights)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not personally aware of any consideration to that extent, but I'd be curious as well. I think it's a change we could choose to make down the line also.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have mentally put rem off the table, one because it's almost impossible to transform an existing app into truly rem-compatible (dynamic) styling, and two because WP is not even 1 rem = 16px 😱

I'm interested in the px/unitless decision for line-height. That has a lot of implications, not only on new things, but for migrations of existing styles (almost all unitless?).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re line-height, I assumed that unitless was always the better approach, since we can have just a few values and mix-and-match them with different font sizes as needed.

"$type": "dimension",
"x-small": {
"xs": {
"$value": { "value": 16, "unit": "px" },
"$description": "Extra small line height"
},
"small": {
"sm": {
"$value": { "value": 20, "unit": "px" },
"$description": "Small line height"
},
"medium": {
"md": {
"$value": { "value": 24, "unit": "px" },
"$description": "Medium line height"
},
"large": {
"lg": {
"$value": { "value": 28, "unit": "px" },
"$description": "Large line height"
},
"x-large": {
"xl": {
"$value": { "value": 32, "unit": "px" },
"$description": "Extra large line height"
},
"2x-large": {
"2xl": {
"$value": { "value": 40, "unit": "px" },
"$description": "2X large line height"
}
},
"weight": {
"$type": "fontWeight",
"regular": {
"$value": 400,
"$description": "Regular font weight for body text"
},
"medium": {
"$value": 499,
"$description": "Medium font weight for emphasis and headings"
}
Comment on lines +94 to +101

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% on these tokens, and would welcome feedback. These are being carried forward from existing variables:

// Weights
$font-weight-regular: 400;
$font-weight-medium: 499; // ensures fallback to 400 (instead of 600)

Note that I did not use the 499 value here, since this is essentially a browser-specific quirk. As such, it might make sense to apply that transformation as part of the CSS transformation, but the raw value and how it's used elsewhere (e.g. Figma) should be 500.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being a browser app, isn't it plausible that the same quirk would manifest in Figma though?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being a browser app, isn't it plausible that the same quirk would manifest in Figma though?

That's a good question. I'm not really sure. Doing some brief inspecting, it looks like the main canvas area in Figma is a <canvas /> element, so I'm not sure if it'd have the same issue.

I think the root of the decision here is codifying the decision that we want 500 as the value in the source design tokens, and dealing with the implementation details as close to the consumption-level as we can manage.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to ship with 499 until we do actually put in place whatever implementation-side handling is necessary?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, let's go with that. Updated in 5d57c17 . This also means it'll be 499 in Figma, which may be what we want or expect, but may also be slightly misaligned.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it on the web version of Figma on Windows OS, but it seems that Segoe UI cannot be selected in the first place.

image

On the other hand, in a local app, I can select Segoe UI, but I cannot enter a font weight numerically.

image image

It seems like 500 is probably fine for design tokens.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for testing @t-hamano ! I'd guess "Semibold" could work here to check. You could also import the tokens themselves as Figma variables so you could use the variable option to check.

}
}
}
6 changes: 3 additions & 3 deletions packages/ui/src/badge/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ export const Badge = forwardRef< HTMLDivElement, BadgeProps >( function Badge(
render={ render }
style={ {
fontFamily: 'var(--wpds-font-family-body)',
fontSize: 'var(--wpds-font-size-small)',
fontWeight: '400',
lineHeight: 'var(--wpds-font-line-height-x-small)',
fontSize: 'var(--wpds-font-size-sm)',
fontWeight: 'var(--wpds-font-weight-regular)',
lineHeight: 'var(--wpds-font-line-height-xs)',
...props.style,
} }
ref={ ref }
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './box';
export * from './badge';
export * from './box';
export * from './form/primitives';
export * from './stack';
export * from './visually-hidden';
12 changes: 6 additions & 6 deletions packages/ui/src/utils/css/field.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@

@layer wp-ui-utilities {
.label {
--wp-ui-field-label-line-height: var(--wpds-font-line-height-x-small);
--wp-ui-field-label-line-height: var(--wpds-font-line-height-xs);

font-family: var(--wpds-font-family-body);
font-size: var(--wpds-font-size-x-small);
font-size: var(--wpds-font-size-xs);
line-height: var(--wp-ui-field-label-line-height);
font-weight: 499; /* TODO: Use variable? */
font-weight: var(--wpds-font-weight-medium);
text-transform: uppercase;
color: var(--wpds-color-fg-content-neutral);

&.is-plain {
font-size: var(--wpds-font-size-medium);
font-size: var(--wpds-font-size-md);
text-transform: none;
}
}

.description {
margin: 0;
font-family: var(--wpds-font-family-body);
font-size: var(--wpds-font-size-small);
line-height: var(--wpds-font-line-height-x-small);
font-size: var(--wpds-font-size-sm);
line-height: var(--wpds-font-line-height-xs);
color: var(--wpds-color-fg-content-neutral-weak);
}
}
Loading