Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions packages/theme/bin/terrazzo-plugin-inline-alias-values/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { type Plugin } from '@terrazzo/parser';
import { type Plugin, type TokenNormalized } from '@terrazzo/parser';

interface InlineAliasValuesOptions {
/**
Expand Down Expand Up @@ -40,25 +40,54 @@ export default function inlineAliasValues( {
return {
name: '@wordpress/terrazzo-plugin-inline-alias-values',
async transform( { tokens } ) {
Object.keys( tokens )
.filter( ( id ) => pattern.test( id ) )
.forEach( ( id ) => {
const token = tokens[ id ];
// Map of primitive token ID -> array of references to inline
const inlineMap: Record< string, TokenNormalized[] > = {};

// Single pass: identify primitives and collect references
for ( const [ id, token ] of Object.entries( tokens ) ) {
const shouldInline = pattern.test( id );

if ( shouldInline ) {
// Track this token for inlining
inlineMap[ id ] = [];

// Track aliased tokens for output file
if ( token.aliasedBy ) {
aliasedBy[ tokenId( id ) ] =
token.aliasedBy.map( tokenId );
}
}

// Check if this token's main value references a primitive
if ( token.aliasOf && pattern.test( token.aliasOf ) ) {
inlineMap[ token.aliasOf ] ??= [];
inlineMap[ token.aliasOf ].push( token );
}

for ( const aliasedId of token.aliasedBy ) {
Object.assign( tokens[ aliasedId ], {
$value: token.$value,
mode: token.mode,
originalValue: token.originalValue,
} );
}
// Check if any mode values reference a primitive
for ( const modeValue of Object.values( token.mode ) ) {
const { aliasOf } = modeValue;
if ( aliasOf && pattern.test( aliasOf ) ) {
const primitiveId = aliasOf;
inlineMap[ primitiveId ] ??= [];
inlineMap[ primitiveId ].push( modeValue );
}
}
}

// Inline values and delete primitives
for ( const [ id, references ] of Object.entries( inlineMap ) ) {
const token = tokens[ id ];

delete tokens[ id ];
} );
for ( const target of references ) {
target.$value = token.$value;
target.originalValue = token.originalValue;
delete target.aliasOf;
delete target.aliasChain;
}

delete tokens[ id ];
}
},
async build( { outputFile } ) {
if ( ! filename ) {
Expand Down
15 changes: 8 additions & 7 deletions packages/theme/docs/ds-tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,14 @@ Do not edit directly.

### Dimension

| Variable name | Description |
| ------------------------------------------ | -------------------------------- |
| `--wpds-dimension-base` | Base dimension unit |
| `--wpds-dimension-padding-surface-x-small` | Extra small spacing for surfaces |
| `--wpds-dimension-padding-surface-small` | Small spacing for surfaces |
| `--wpds-dimension-padding-surface-medium` | Medium spacing for surfaces |
| `--wpds-dimension-padding-surface-large` | Large spacing for surfaces |
| Variable name | Description |
| -------------------------------------- | ----------------------------------- |
| `--wpds-dimension-base` | Base dimension unit |
| `--wpds-dimension-padding-surface-2xs` | 2x extra small spacing for surfaces |
| `--wpds-dimension-padding-surface-xs` | Extra small spacing for surfaces |
| `--wpds-dimension-padding-surface-sm` | Small spacing for surfaces |
| `--wpds-dimension-padding-surface-md` | Medium spacing for surfaces |
| `--wpds-dimension-padding-surface-lg` | Large spacing for surfaces |

### Elevation

Expand Down
25 changes: 21 additions & 4 deletions packages/theme/src/prebuilt/css/design-tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,11 @@
--wpds-color-stroke-surface-warning: #d2b581; /* Decorative stroke color used to define warning-toned surface boundaries with normal emphasis. */
--wpds-color-stroke-surface-warning-strong: #936400; /* Decorative stroke color used to define warning-toned surface boundaries with strong emphasis. */
--wpds-dimension-base: 4px; /* Base dimension unit */
--wpds-dimension-padding-surface-large: 24px; /* Large spacing for surfaces */
--wpds-dimension-padding-surface-medium: 16px; /* Medium spacing for surfaces */
--wpds-dimension-padding-surface-small: 12px; /* Small spacing for surfaces */
--wpds-dimension-padding-surface-x-small: 8px; /* Extra small spacing for surfaces */
--wpds-dimension-padding-surface-2xs: 4px; /* 2x extra small spacing for surfaces */
--wpds-dimension-padding-surface-lg: 32px; /* Large spacing for surfaces */
--wpds-dimension-padding-surface-md: 24px; /* Medium spacing for surfaces */
--wpds-dimension-padding-surface-sm: 16px; /* Small spacing for surfaces */
--wpds-dimension-padding-surface-xs: 8px; /* Extra small spacing for surfaces */
--wpds-elevation-large: 0 5px 15px 0 #00000014, 0 15px 27px 0 #00000012,
0 30px 36px 0 #0000000a, 0 50px 43px 0 #00000005; /* For components that confirm decisions or handle necessary interruptions. Example: Modals. */
--wpds-elevation-medium: 0 2px 3px 0 #0000000d, 0 4px 5px 0 #0000000a,
Expand Down Expand Up @@ -127,6 +128,22 @@
--wpds-font-size-x-small: 11px; /* Extra small font size */
}

[data-wpds-theme-provider-id][data-wpds-density='compact'] {
--wpds-dimension-padding-surface-2xs: 4px; /* 2x extra small spacing for surfaces */
--wpds-dimension-padding-surface-lg: 24px; /* Large spacing for surfaces */
--wpds-dimension-padding-surface-md: 20px; /* Medium spacing for surfaces */
--wpds-dimension-padding-surface-sm: 12px; /* Small spacing for surfaces */
--wpds-dimension-padding-surface-xs: 4px; /* Extra small spacing for surfaces */
}

[data-wpds-theme-provider-id][data-wpds-density='comfortable'] {
--wpds-dimension-padding-surface-2xs: 8px; /* 2x extra small spacing for surfaces */
--wpds-dimension-padding-surface-lg: 40px; /* Large spacing for surfaces */
--wpds-dimension-padding-surface-md: 32px; /* Medium spacing for surfaces */
--wpds-dimension-padding-surface-sm: 20px; /* Small spacing for surfaces */
--wpds-dimension-padding-surface-xs: 12px; /* Extra small spacing for surfaces */
}

Comment on lines +140 to +155

@jameskoster jameskoster Nov 13, 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.

I don't have a strong opinion but I'm wondering if a naming convention like xs, sm, md, lg, xl would be better.

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 we could still change it at this point if we think it'd be an improvement. For context, these are largely carried over from existing conventions like what exist in base-styles (example)

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 the shorter names are a bit easier to interpret when the scale grows. IE 4xs is slightly more intuitive than 4-x-small. It also makes the tokens names shorter, and a bit easier to scan in a list. So I think I lean in that direction, but only slightly. Keen to hear other thoughts cc @mattmiklic.

@media ( -webkit-min-device-pixel-ratio: 2 ), ( min-resolution: 192dpi ) {
:root {
--wpds-border-width-focus: 1.5px; /* Border width for focus ring */
Expand Down
9 changes: 5 additions & 4 deletions packages/theme/src/prebuilt/js/design-tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,11 @@ export default [
'--wpds-color-stroke-interactive-error-strong',
'--wpds-color-stroke-focus-brand',
'--wpds-dimension-base',
'--wpds-dimension-padding-surface-x-small',
'--wpds-dimension-padding-surface-small',
'--wpds-dimension-padding-surface-medium',
'--wpds-dimension-padding-surface-large',
'--wpds-dimension-padding-surface-2xs',
'--wpds-dimension-padding-surface-xs',
'--wpds-dimension-padding-surface-sm',
'--wpds-dimension-padding-surface-md',
'--wpds-dimension-padding-surface-lg',
'--wpds-elevation-x-small',
'--wpds-elevation-small',
'--wpds-elevation-medium',
Expand Down
32 changes: 24 additions & 8 deletions packages/theme/src/prebuilt/json/figma.json
Original file line number Diff line number Diff line change
Expand Up @@ -558,27 +558,43 @@
},
"description": "Base dimension unit"
},
"Dimension/Semantic/padding-surface-x-small": {
"Dimension/Semantic/padding-surface-2xs": {
"value": {
".": "8px"
".": "4px",
"compact": "4px",
"comfortable": "8px"
},
"description": "2x extra small spacing for surfaces"
},
"Dimension/Semantic/padding-surface-xs": {
"value": {
".": "8px",
"compact": "4px",
"comfortable": "12px"
Comment thread
aduth marked this conversation as resolved.
Resolved
},
"description": "Extra small spacing for surfaces"
},
"Dimension/Semantic/padding-surface-small": {
"Dimension/Semantic/padding-surface-sm": {
"value": {
".": "12px"
".": "16px",
"compact": "12px",
"comfortable": "20px"
},
"description": "Small spacing for surfaces"
},
"Dimension/Semantic/padding-surface-medium": {
"Dimension/Semantic/padding-surface-md": {
"value": {
".": "16px"
".": "24px",
"compact": "20px",
"comfortable": "32px"
},
"description": "Medium spacing for surfaces"
},
"Dimension/Semantic/padding-surface-large": {
"Dimension/Semantic/padding-surface-lg": {
"value": {
".": "24px"
".": "32px",
"compact": "24px",
"comfortable": "40px"
},
"description": "Large spacing for surfaces"
},

@jameskoster jameskoster Nov 13, 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.

I think we'll probably need tokens for 32px and 48px padding. 32px is currently used in Dialogs and 48px in DataViews.

I guess that also means we'll need a new primitive so that 48px can jump to 56px in comfortable density.

Expand Down
24 changes: 18 additions & 6 deletions packages/theme/src/stories/index.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,10 @@ export const WithPicker: StoryObj< typeof ThemeProvider > = {
},
};

const NestingDebug = ( { bg = '', primary = '' } ) => (
const NestingDebug = ( { bg = '', primary = '', density = '' } ) => (
Comment thread
aduth marked this conversation as resolved.
Resolved
<div
style={ {
padding: '0.25rem',
padding: 'var(--wpds-dimension-padding-surface-small)',
Comment thread
aduth marked this conversation as resolved.
Resolved
color: 'var(--wpds-color-fg-content-neutral)',
backgroundColor: 'var(--wpds-color-bg-surface-neutral)',
display: 'flex',
Expand All @@ -210,8 +210,8 @@ const NestingDebug = ( { bg = '', primary = '' } ) => (
gap: '1rem',
} }
>
<pre>
bg: { bg } | primary: { primary }
<pre style={ { margin: 0 } }>
bg: { bg } | primary: { primary } | density: { density }
</pre>
<span
style={ {
Expand Down Expand Up @@ -245,19 +245,29 @@ export const NestingAndInheriting: StoryObj< typeof ThemeProvider > = {
render: () => {
return (
<ThemeProvider>
<NestingDebug bg="inherit (root)" primary="inherit (root)" />
<NestingDebug
bg="inherit (root)"
primary="inherit (root)"
density="inherit (root)"
/>
<div style={ { paddingInlineStart: '1rem' } }>
<ThemeProvider
color={ {
bg: '#1e1e1e',
} }
density="compact"
>
<NestingDebug bg="#1e1e1e" primary="inherit (root)" />
<NestingDebug
bg="#1e1e1e"
primary="inherit (root)"
density="compact"
/>
<div style={ { paddingInlineStart: '1rem' } }>
<ThemeProvider>
<NestingDebug
bg="inherit (#1e1e1e)"
primary="inherit (root)"
density="inherit (compact)"
/>
<div style={ { paddingInlineStart: '1rem' } }>
<ThemeProvider
Expand All @@ -266,6 +276,7 @@ export const NestingAndInheriting: StoryObj< typeof ThemeProvider > = {
<NestingDebug
bg="inherit (#1e1e1e)"
primary="hotpink"
density="inherit (compact)"
/>
<div
style={ {
Expand All @@ -278,6 +289,7 @@ export const NestingAndInheriting: StoryObj< typeof ThemeProvider > = {
<NestingDebug
bg="#f8f8f8"
primary="inherit (hotpink)"
density="inherit (compact)"
/>
</ThemeProvider>
</div>
Expand Down
2 changes: 2 additions & 0 deletions packages/theme/src/theme-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const ThemeProvider = ( {
children,
color = {},
isRoot = false,
density,
}: ThemeProviderProps ) => {
const instanceId = useId();

Expand Down Expand Up @@ -76,6 +77,7 @@ export const ThemeProvider = ( {
<div
data-wpds-theme-provider-id={ instanceId }
data-wpds-root-provider={ isRoot }
data-wpds-density={ density }
className={ styles.root }
>
<ThemeContext.Provider value={ contextValue }>
Expand Down
5 changes: 5 additions & 0 deletions packages/theme/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export interface ThemeProviderSettings {
*/
bg?: string;
};

/**
* The density of the theme.
*/
density?: 'compact' | 'comfortable';

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.

Should there be a middle-ground default, 'balanced' or similar?

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.

Ah, I understand there is a default, but it's not named. Feel free to resolve :D

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.

Yeah, the absence of an override is considered the default. We could have something more explicit, though I think this mirrors nicely to the way it works in the tokens, which is that the densities are "extensions" (i.e. overrides) to some base value.

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 should at least mention in the prop description that it's going to use some other default density as the default. As it looks to a consumer now, we might as well just forgotten to document whether the default is compact or comfortable.

}

export interface ThemeProviderProps extends ThemeProviderSettings {
Expand Down
12 changes: 12 additions & 0 deletions packages/theme/terrazzo.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ export default defineConfig( {
makeCSSVar( `wpds.${ publicTokenId( token.id ) }` ),
baseSelector: ':root',
modeSelectors: [
{
mode: 'compact',
selectors: [
"[data-wpds-theme-provider-id][data-wpds-density='compact']",
],
},
{
mode: 'comfortable',
selectors: [
"[data-wpds-theme-provider-id][data-wpds-density='comfortable']",
],
},
{
mode: 'high-dpi',
selectors: [
Expand Down
54 changes: 44 additions & 10 deletions packages/theme/tokens/dimension.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,55 @@
},
"padding": {
"surface": {
"x-small": {
"$value": "{dimension.primitive.space.20}",
"$description": "Extra small spacing for surfaces"
"2xs": {
"$value": "{dimension.primitive.space.10}",
"$description": "2x extra small spacing for surfaces",
"$extensions": {
"mode": {
"compact": "{dimension.primitive.space.10}",
"comfortable": "{dimension.primitive.space.20}"
}
}
},
"small": {
"$value": "{dimension.primitive.space.30}",
"$description": "Small spacing for surfaces"
"xs": {
"$value": "{dimension.primitive.space.20}",
"$description": "Extra small spacing for surfaces",
"$extensions": {
"mode": {
"compact": "{dimension.primitive.space.10}",
"comfortable": "{dimension.primitive.space.30}"
}
}
},
"medium": {
"sm": {
"$value": "{dimension.primitive.space.40}",
"$description": "Medium spacing for surfaces"
"$description": "Small spacing for surfaces",
"$extensions": {
"mode": {
"compact": "{dimension.primitive.space.30}",
"comfortable": "{dimension.primitive.space.50}"
}
}
},
"large": {
"md": {
"$value": "{dimension.primitive.space.60}",
"$description": "Large spacing for surfaces"
"$description": "Medium spacing for surfaces",
"$extensions": {
"mode": {
"compact": "{dimension.primitive.space.50}",
"comfortable": "{dimension.primitive.space.70}"
}
}
},
"lg": {
"$value": "{dimension.primitive.space.70}",
"$description": "Large spacing for surfaces",
"$extensions": {
"mode": {
"compact": "{dimension.primitive.space.60}",
"comfortable": "{dimension.primitive.space.80}"
}
}
}
}
}
Expand Down
Loading
Loading