Skip to content

Commit 571b2c9

Browse files
committed
Theme: Keep injected admin fallback variables global
1 parent b8f205e commit 571b2c9

4 files changed

Lines changed: 46 additions & 19 deletions

File tree

‎packages/theme/CHANGELOG.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
- Avoid intercepting esbuild virtual modules, preserve root custom-property priorities on cleanup, and reject non-finite RGB seed channels while treating missing (`none`) RGB channels as zero. ([#83355](https://github.com/WordPress/gutenberg/pull/83355))
88
- Make JavaScript token fallback transforms syntax-aware, preserve tagged-template values and source maps, and support Vite query-string module IDs. Use the TypeScript loader for `.ts`, `.mts`, and `.cts` files handled by the esbuild plugin, including files whose token values are unchanged. ([#83356](https://github.com/WordPress/gutenberg/pull/83356))
9-
- Preserve Lightning CSS `from global` references when injecting design token fallbacks ([#83359](https://github.com/WordPress/gutenberg/pull/83359)).
9+
- Preserve Lightning CSS `from global` references and keep nested fallback variables global when injecting design token fallbacks ([#83359](https://github.com/WordPress/gutenberg/pull/83359)).
1010

1111
## 2.2.0 (2026-09-23)
1212

‎packages/theme/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ const { code } = transform( {
310310
} );
311311
```
312312

313-
The visitor preserves CSS Modules [`from global`](https://lightningcss.dev/css-modules.html#local-css-variables) references such as `var(--wpds-dimension-gap-sm from global)` when it adds a fallback.
313+
The visitor preserves CSS Modules [`from global`](https://lightningcss.dev/css-modules.html#local-css-variables) references such as `var(--wpds-dimension-gap-sm from global)` when it adds a fallback. Custom properties inside generated fallbacks, including `--wp-admin-*` variables, also remain global so admin overrides still apply.
314314

315315
### esbuild
316316

‎packages/theme/lightningcss-plugins/lightningcss-ds-token-fallbacks.mjs‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ transform( {
2323
variable.fallback &&
2424
Object.hasOwn( tokenFallbacks, variable.name.ident )
2525
) {
26-
// Lightning CSS returns `from: null` in visited nodes but
27-
// requires null specifiers to be omitted from returned nodes.
26+
// Generated fallbacks reference global custom properties.
27+
// Keep CSS Modules from scoping them to the consumer's file.
2828
const fallback = JSON.parse(
2929
JSON.stringify( variable.fallback, ( key, value ) =>
30-
key === 'from' && value === null ? undefined : value
30+
key === 'from' && value === null
31+
? { type: 'global' }
32+
: value
3133
)
3234
);
3335
parsedFallbacks.set( variable.name.ident, fallback );

‎packages/theme/src/test/build-plugin-parity.test.ts‎

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -143,21 +143,46 @@ describe( 'design token fallback build plugin parity', () => {
143143
expect( lightningcssResult ).toContain( expected );
144144
} );
145145

146-
it( 'preserves from global when adding a fallback with Lightning CSS', () => {
147-
const result = lightningcssTransform( {
148-
filename: 'styles.module.css',
149-
code: Buffer.from(
150-
'.fixture { gap: var(--wpds-dimension-gap-sm from global); }'
151-
),
152-
cssModules: { dashedIdents: true },
153-
visitor: lightningcssPlugin,
154-
} );
146+
it.each( [
147+
{
148+
property: 'gap',
149+
token: '--wpds-dimension-gap-sm',
150+
fallback: '8px',
151+
},
152+
{
153+
property: 'outline-width',
154+
token: '--wpds-border-width-focus',
155+
fallback: 'var(--wp-admin-border-width-focus, 2px)',
156+
},
157+
{
158+
property: 'background-color',
159+
token: '--wpds-color-background-interactive-brand-strong',
160+
fallback: 'var(--wp-admin-theme-color, #3858e9)',
161+
},
162+
{
163+
property: 'background-color',
164+
token: '--wpds-color-background-interactive-brand-strong-active',
165+
fallback:
166+
'color-mix(in oklch, var(--wp-admin-theme-color, #3858e9) 93.0%, black)',
167+
},
168+
] )(
169+
'preserves global references in $token and its fallback with Lightning CSS',
170+
( { property, token, fallback } ) => {
171+
const result = lightningcssTransform( {
172+
filename: 'styles.module.css',
173+
code: Buffer.from(
174+
`.fixture { ${ property }: var(${ token } from global); }`
175+
),
176+
cssModules: { dashedIdents: true },
177+
visitor: lightningcssPlugin,
178+
} );
155179

156-
expect( result.code.toString() ).toContain(
157-
'gap: var(--wpds-dimension-gap-sm, 8px)'
158-
);
159-
expect( result.references ).toEqual( {} );
160-
} );
180+
expect( result.code.toString() ).toContain(
181+
`${ property }: var(${ token }, ${ fallback })`
182+
);
183+
expect( result.references ).toEqual( {} );
184+
}
185+
);
161186

162187
it( 'isolates injected fallbacks from changes by composed Lightning CSS visitors', () => {
163188
const source = '.fixture { gap: var(--wpds-dimension-gap-sm); }';

0 commit comments

Comments
 (0)