Skip to content

Commit 5e3968b

Browse files
authored
Merge 47db752 into ce00be1
2 parents ce00be1 + 47db752 commit 5e3968b

13 files changed

Lines changed: 570 additions & 5 deletions

File tree

‎packages/theme/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
### Internal
1717

18+
- Generate and commit complete border radius and width tokens for Figma mode imports during the theme build. ([#84035](https://github.com/WordPress/gutenberg/pull/84035))
1819
- Update the Vite development dependency to 8.3.2 ([#83992](https://github.com/WordPress/gutenberg/pull/83992)).
1920
- Update the Vite development dependency to 8.3.1. ([#83569](https://github.com/WordPress/gutenberg/pull/83569))
2021
- Restore color-scale Storybook accessibility checks with labeled color samples, readable seed labels, and keyboard scrolling ([#83358](https://github.com/WordPress/gutenberg/pull/83358)).

‎packages/theme/README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ This step will:
277277
2. Generate primitive tokens.
278278
3. Build CSS and JavaScript token files.
279279
4. Update the design tokens documentation.
280-
5. Format all generated files.
280+
5. Generate complete Figma border collection mode files in `prebuilt/figma`.
281+
6. Format all generated files.
281282

282283
The files generated in this step will all be committed to the repo.
283284

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type { Resolver } from '@terrazzo/parser';
2+
3+
/**
4+
* Generate complete DTCG files for independent Figma border collections.
5+
*
6+
* @param resolver The parsed design token resolver.
7+
* @return One import file per collection mode.
8+
*/
9+
export function generateFigmaFiles( resolver: Resolver ) {
10+
const files: { filename: string; contents: string }[] = [];
11+
12+
for ( const [ group, modifier ] of [
13+
[ 'radius', 'corner-radius' ],
14+
[ 'width', 'pixel-density' ],
15+
] ) {
16+
const contexts = resolver.source.modifiers?.[ modifier ]?.contexts;
17+
if ( ! contexts ) {
18+
throw new Error(
19+
`Missing Figma collection modifier: ${ modifier }`
20+
);
21+
}
22+
23+
for ( const mode of Object.keys( contexts ) ) {
24+
const tokens = resolver.apply(
25+
{ [ modifier ]: mode },
26+
{ modifiers: [ modifier ], resolveAliases: false }
27+
);
28+
const contents: Record< string, unknown > = {};
29+
30+
for ( const [ id, token ] of Object.entries( tokens ) ) {
31+
if ( ! id.startsWith( `wpds-border.${ group }.` ) ) {
32+
continue;
33+
}
34+
35+
// Keep the original hierarchy so Figma variable names still match.
36+
const path = id.split( '.' );
37+
const name = path.pop()!;
38+
let parent = contents;
39+
for ( const segment of path ) {
40+
parent[ segment ] ??= {};
41+
parent = parent[ segment ] as Record< string, unknown >;
42+
}
43+
parent[ name ] = {
44+
$type: token.$type,
45+
$value: token.$value,
46+
$description: token.$description,
47+
$extensions: token.$extensions,
48+
$deprecated: token.$deprecated,
49+
};
50+
}
51+
52+
files.push( {
53+
filename: `${ group }/${ mode }.json`,
54+
contents: JSON.stringify( contents, null, '\t' ) + '\n',
55+
} );
56+
}
57+
}
58+
59+
return files;
60+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
2+
import { dirname } from 'node:path';
3+
import { fileURLToPath } from 'node:url';
4+
import { parse } from '@terrazzo/parser';
5+
import config from '../../terrazzo.config.ts';
6+
import { generateFigmaFiles } from './generate.ts';
7+
8+
const sources = await Promise.all(
9+
config.tokens.map( async ( filename: URL ) => ( {
10+
filename,
11+
src: await readFile( filename, 'utf8' ),
12+
} ) )
13+
);
14+
const { resolver } = await parse( sources, { config } );
15+
16+
for ( const file of generateFigmaFiles( resolver ) ) {
17+
const filename = new URL(
18+
`../../prebuilt/figma/${ file.filename }`,
19+
import.meta.url
20+
);
21+
await mkdir( dirname( fileURLToPath( filename ) ), { recursive: true } );
22+
await writeFile( filename, file.contents );
23+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { readFile } from 'node:fs/promises';
2+
import { beforeAll, describe, expect, it } from 'vitest';
3+
import { parse } from '@terrazzo/parser';
4+
import config from '../../../terrazzo.config.ts';
5+
import { generateFigmaFiles } from '../generate.ts';
6+
7+
describe( 'Figma border collection files', () => {
8+
let files: ReturnType< typeof generateFigmaFiles >;
9+
let border: Record<
10+
string,
11+
Record<
12+
string,
13+
{
14+
$description?: string;
15+
$extensions?: Record< string, unknown >;
16+
}
17+
>
18+
>;
19+
20+
beforeAll( async () => {
21+
const sources = await Promise.all(
22+
config.tokens.map( async ( filename: URL ) => ( {
23+
filename,
24+
src: await readFile( filename, 'utf8' ),
25+
} ) )
26+
);
27+
const { resolver } = await parse( sources, { config } );
28+
files = generateFigmaFiles( resolver );
29+
border = JSON.parse(
30+
await readFile(
31+
new URL( '../../../tokens/border.json', import.meta.url ),
32+
'utf8'
33+
)
34+
)[ 'wpds-border' ];
35+
} );
36+
37+
it( 'creates complete mode files with the original names, types, descriptions, and scopes', () => {
38+
expect( files.map( ( file ) => file.filename ) ).toEqual( [
39+
'radius/none.json',
40+
'radius/subtle.json',
41+
'radius/moderate.json',
42+
'radius/pronounced.json',
43+
'width/standard.json',
44+
'width/high-dpi.json',
45+
] );
46+
47+
for ( const file of files ) {
48+
const group = file.filename.split( '/' )[ 0 ];
49+
const document = JSON.parse( file.contents );
50+
expect( Object.keys( document ) ).toEqual( [ 'wpds-border' ] );
51+
expect( Object.keys( document[ 'wpds-border' ] ) ).toEqual( [
52+
group,
53+
] );
54+
const tokens = document[ 'wpds-border' ][ group ];
55+
const names = Object.keys( border[ group ] ).filter(
56+
( name ) => ! name.startsWith( '$' )
57+
);
58+
expect( Object.keys( tokens ) ).toEqual( names );
59+
for ( const name of names ) {
60+
expect( tokens[ name ] ).toEqual( {
61+
$type: 'dimension',
62+
$value: { value: expect.any( Number ), unit: 'px' },
63+
$description: border[ group ][ name ].$description,
64+
$extensions: border[ group ][ name ].$extensions,
65+
} );
66+
}
67+
}
68+
} );
69+
} );

‎packages/theme/package.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@
159159
"scripts": {
160160
"build:default-ramps": "node bin/generate-default-ramps/index.ts",
161161
"build:tokens": "node bin/generate-primitive-tokens/index.ts && node bin/build-design-tokens/index.ts",
162-
"build": "npm run build:default-ramps && npm run build:tokens",
162+
"build:figma": "node bin/build-figma-tokens/index.ts",
163+
"build": "npm run build:default-ramps && npm run build:tokens && npm run build:figma",
163164
"lint:package-contents": "wp-validate-package-contents . --disallow-path src",
164165
"postbuild": "prettier --write tokens/color.json tokens/modes prebuilt src/prebuilt src/color-ramps/lib/default-ramps.ts docs ../base-styles/internal/_wpds-token-fallbacks.scss"
165166
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"wpds-border": {
3+
"radius": {
4+
"xs": {
5+
"$type": "dimension",
6+
"$value": {
7+
"value": 6,
8+
"unit": "px"
9+
},
10+
"$description": "Buttons and other elements nested inside controls.",
11+
"$extensions": {
12+
"com.figma.scopes": [ "CORNER_RADIUS" ]
13+
}
14+
},
15+
"sm": {
16+
"$type": "dimension",
17+
"$value": {
18+
"value": 8,
19+
"unit": "px"
20+
},
21+
"$description": "Standalone buttons, inputs, and compact controls.",
22+
"$extensions": {
23+
"com.figma.scopes": [ "CORNER_RADIUS" ]
24+
}
25+
},
26+
"md": {
27+
"$type": "dimension",
28+
"$value": {
29+
"value": 12,
30+
"unit": "px"
31+
},
32+
"$description": "Menus, popovers, and other small portaled overlays.",
33+
"$extensions": {
34+
"com.figma.scopes": [ "CORNER_RADIUS" ]
35+
}
36+
},
37+
"lg": {
38+
"$type": "dimension",
39+
"$value": {
40+
"value": 16,
41+
"unit": "px"
42+
},
43+
"$description": "Cards, dialogs, notices, and other larger content containers.",
44+
"$extensions": {
45+
"com.figma.scopes": [ "CORNER_RADIUS" ]
46+
}
47+
},
48+
"xl": {
49+
"$type": "dimension",
50+
"$value": {
51+
"value": 20,
52+
"unit": "px"
53+
},
54+
"$description": "Page and app shell surfaces.",
55+
"$extensions": {
56+
"com.figma.scopes": [ "CORNER_RADIUS" ]
57+
}
58+
}
59+
}
60+
}
61+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"wpds-border": {
3+
"radius": {
4+
"xs": {
5+
"$type": "dimension",
6+
"$value": {
7+
"value": 0,
8+
"unit": "px"
9+
},
10+
"$description": "Buttons and other elements nested inside controls.",
11+
"$extensions": {
12+
"com.figma.scopes": [ "CORNER_RADIUS" ]
13+
}
14+
},
15+
"sm": {
16+
"$type": "dimension",
17+
"$value": {
18+
"value": 0,
19+
"unit": "px"
20+
},
21+
"$description": "Standalone buttons, inputs, and compact controls.",
22+
"$extensions": {
23+
"com.figma.scopes": [ "CORNER_RADIUS" ]
24+
}
25+
},
26+
"md": {
27+
"$type": "dimension",
28+
"$value": {
29+
"value": 0,
30+
"unit": "px"
31+
},
32+
"$description": "Menus, popovers, and other small portaled overlays.",
33+
"$extensions": {
34+
"com.figma.scopes": [ "CORNER_RADIUS" ]
35+
}
36+
},
37+
"lg": {
38+
"$type": "dimension",
39+
"$value": {
40+
"value": 0,
41+
"unit": "px"
42+
},
43+
"$description": "Cards, dialogs, notices, and other larger content containers.",
44+
"$extensions": {
45+
"com.figma.scopes": [ "CORNER_RADIUS" ]
46+
}
47+
},
48+
"xl": {
49+
"$type": "dimension",
50+
"$value": {
51+
"value": 0,
52+
"unit": "px"
53+
},
54+
"$description": "Page and app shell surfaces.",
55+
"$extensions": {
56+
"com.figma.scopes": [ "CORNER_RADIUS" ]
57+
}
58+
}
59+
}
60+
}
61+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"wpds-border": {
3+
"radius": {
4+
"xs": {
5+
"$type": "dimension",
6+
"$value": {
7+
"value": 18,
8+
"unit": "px"
9+
},
10+
"$description": "Buttons and other elements nested inside controls.",
11+
"$extensions": {
12+
"com.figma.scopes": [ "CORNER_RADIUS" ]
13+
}
14+
},
15+
"sm": {
16+
"$type": "dimension",
17+
"$value": {
18+
"value": 20,
19+
"unit": "px"
20+
},
21+
"$description": "Standalone buttons, inputs, and compact controls.",
22+
"$extensions": {
23+
"com.figma.scopes": [ "CORNER_RADIUS" ]
24+
}
25+
},
26+
"md": {
27+
"$type": "dimension",
28+
"$value": {
29+
"value": 22,
30+
"unit": "px"
31+
},
32+
"$description": "Menus, popovers, and other small portaled overlays.",
33+
"$extensions": {
34+
"com.figma.scopes": [ "CORNER_RADIUS" ]
35+
}
36+
},
37+
"lg": {
38+
"$type": "dimension",
39+
"$value": {
40+
"value": 24,
41+
"unit": "px"
42+
},
43+
"$description": "Cards, dialogs, notices, and other larger content containers.",
44+
"$extensions": {
45+
"com.figma.scopes": [ "CORNER_RADIUS" ]
46+
}
47+
},
48+
"xl": {
49+
"$type": "dimension",
50+
"$value": {
51+
"value": 26,
52+
"unit": "px"
53+
},
54+
"$description": "Page and app shell surfaces.",
55+
"$extensions": {
56+
"com.figma.scopes": [ "CORNER_RADIUS" ]
57+
}
58+
}
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)