Skip to content

Commit ddc5e3c

Browse files
matgallajcfranco
andauthored
refactor(tokens): Update JSON files to support Tokens Studio management (#11852)
**Related Issue:** #11391 ## Summary This update makes changes necessary for the modification of Calcite tokens within Tokens Studio. No changes are made to the final tokens themselves in this update. Criteria for completion: - [x] Import current token files into TStudio (TStudio automatically moves things around, but there should be no functional change) - [x] Separate light/dark semantic color tokens into their own files so that TStudio can use them as themes - [x] Change all instances of `"type": "size"` to `"type": "sizing"` For TStudio organization - [x] Change all instances of `"type": "space"` to `"type": "spacing"` For TStudio organization - [x] Change all instances of `"type": "breakpoint"` to `"type": "dimension"` For TStudio organization - [x] Add TStudio themes for different token types This update is one step in the process of moving our token management over to Tokens Studio. ## Next steps - Update snapshot tests - Remove token attributes - Add missing core color tokens - Fix incorrect core color values - Audit the structural differences between tokens and Figma variables - Restructure tokens to align with Figma variables where necessary - Resolve #10050 - Resolve #11565 - Resolve #11581 - Resolve #11725 - Audit the value differences between tokens and Figma variables (mainly for percentages, and typography) - Finalize token and Figma variable values with Calcite designers and developers - Update token values to align with Figma variables where necessary - Document the new token creation and modification process --------- Co-authored-by: JC Franco <jfranco@esri.com>
1 parent 34a663f commit ddc5e3c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2553
-1694
lines changed

Diff for: packages/calcite-design-tokens/src/build-tokens.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
import { semantic } from "./build/dictionaries/index.js";
1+
import { dark, light, semantic } from "./build/dictionaries/index.js";
22

3+
await dark.buildAllPlatforms();
4+
await light.buildAllPlatforms();
35
await semantic.buildAllPlatforms();

Diff for: packages/calcite-design-tokens/src/build/dictionaries/index.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import StyleDictionary from "style-dictionary";
22
import { register as registerTokenStudioTransformers } from "@tokens-studio/sd-transforms";
3-
import calciteLightConfig from "../../config/calcite/light.js";
4-
import calciteDarkConfig from "../../config/calcite/dark.js";
3+
import calciteLightConfig from "../../config/color/light.js";
4+
import calciteDarkConfig from "../../config/color/dark.js";
55
import semanticConfig from "../../config/semantic.js";
66
import { register as registerCalciteHooks } from "../registry/index.js";
77
import { applyBuiltInOverrides, applyOverrides } from "../overrides/index.js";
@@ -14,9 +14,9 @@ await registerTokenStudioTransformers(StyleDictionary, {
1414
await registerCalciteHooks(StyleDictionary);
1515
applyOverrides(StyleDictionary);
1616

17-
const semantic = new StyleDictionary(semanticConfig);
1817
const light = new StyleDictionary(calciteLightConfig);
1918
const dark = new StyleDictionary(calciteDarkConfig);
19+
const semantic = new StyleDictionary(semanticConfig);
2020

2121
applyBuiltInOverrides([semantic, light, dark]);
2222

Diff for: packages/calcite-design-tokens/src/build/filter/core.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { Filter } from "style-dictionary/types";
22
import StyleDictionary from "style-dictionary";
33
import { RegisterFn } from "../types/interfaces.js";
4+
import { isLightOrDarkColorToken } from "./light-or-dark.js";
45

5-
export const filterCoreTokens: Filter["filter"] = (token) => !token.isSource && token.type !== "typography";
6+
export const filterCoreTokens: Filter["filter"] = (token, config) =>
7+
!token.isSource && token.type !== "typography" && !isLightOrDarkColorToken(token, config);
68

79
export const registerFilterCoreTokens: RegisterFn = () =>
810
StyleDictionary.registerFilter({

Diff for: packages/calcite-design-tokens/src/build/filter/dark.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ import StyleDictionary from "style-dictionary";
33
import { RegisterFn } from "../types/interfaces.js";
44
import { isThemed } from "../utils/token-types.js";
55

6-
export const filterDarkColorTokens: Filter["filter"] = (token) =>
7-
token.isSource &&
8-
(isThemed(token, { theme: "dark", targetPropName: "filePath" }) ||
9-
isThemed(token, { theme: "dark", targetPropName: "path" }));
6+
export const filterDarkColorTokens: Filter["filter"] = (token) => isThemed(token, { theme: "dark" });
107

118
export const registerFilterDarkColorTokens: RegisterFn = () =>
129
StyleDictionary.registerFilter({

Diff for: packages/calcite-design-tokens/src/build/filter/global-js.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { Filter } from "style-dictionary/types";
22
import StyleDictionary from "style-dictionary";
33
import { RegisterFn } from "../types/interfaces.js";
4+
import { isLightOrDarkColorToken } from "./light-or-dark.js";
45

56
/**
67
* This filter helps match the test snapshot, this can be removed once outputs are consolidated
78
*
89
* @param token
10+
* @param config
911
*/
10-
export const filterGlobalTokensJs: Filter["filter"] = (token) => {
11-
return token.isSource;
12+
export const filterGlobalTokensJs: Filter["filter"] = (token, config) => {
13+
return token.isSource || isLightOrDarkColorToken(token, config);
1214
};
1315

1416
export const registerFilterGlobalTokensJs: RegisterFn = () =>

Diff for: packages/calcite-design-tokens/src/build/filter/global.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { Filter } from "style-dictionary/types";
22
import StyleDictionary from "style-dictionary";
33
import { RegisterFn } from "../types/interfaces.js";
44
import { isBreakpoint } from "../utils/token-types.js";
5+
import { state } from "../shared/state.js";
56
import { isLightOrDarkColorToken } from "./light-or-dark.js";
67

78
export const filterGlobalTokens: Filter["filter"] = (token, config) => {
89
return (
9-
token.isSource && !(token.type === "typography" || isBreakpoint(token) || isLightOrDarkColorToken(token, config))
10+
state.sameValueThemeTokens.has(token.key) ||
11+
(token.isSource && !(token.type === "typography" || isBreakpoint(token) || isLightOrDarkColorToken(token, config)))
1012
);
1113
};
1214

Diff for: packages/calcite-design-tokens/src/build/filter/include.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Filter } from "style-dictionary/types";
22
import StyleDictionary from "style-dictionary";
33
import { RegisterFn } from "../types/interfaces.js";
4+
import { isThemed } from "../utils/token-types.js";
45

5-
export const filterIncludeTokens: Filter["filter"] = (token) => !token.isSource;
6+
export const filterIncludeTokens: Filter["filter"] = (token) => !token.isSource && !isThemed(token);
67

78
export const registerFilterIncludeTokens: RegisterFn = () => {
89
StyleDictionary.registerFilter({

Diff for: packages/calcite-design-tokens/src/build/filter/light-or-dark.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ import StyleDictionary from "style-dictionary";
33
import { RegisterFn } from "../types/interfaces.js";
44
import { isThemed } from "../utils/token-types.js";
55

6-
export const isLightOrDarkColorToken: Filter["filter"] = (token) =>
7-
isThemed(token, { targetPropName: "filePath" }) || isThemed(token, { targetPropName: "path" });
6+
export const isLightOrDarkColorToken: Filter["filter"] = (token) => isThemed(token);
87

9-
const filterLightOrDarkColorTokens: Filter["filter"] = (token) =>
10-
token.isSource && (isThemed(token, { targetPropName: "filePath" }) || isThemed(token, { targetPropName: "path" }));
8+
const filterLightOrDarkColorTokens: Filter["filter"] = (token) => !token.isSource && isThemed(token);
119

1210
export const registerFilterLightOrDarkColorTokens: RegisterFn = () =>
1311
StyleDictionary.registerFilter({

Diff for: packages/calcite-design-tokens/src/build/filter/light.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ import StyleDictionary from "style-dictionary";
33
import { RegisterFn } from "../types/interfaces.js";
44
import { isThemed } from "../utils/token-types.js";
55

6-
export const filterLightColorTokens: Filter["filter"] = (token) =>
7-
token.isSource &&
8-
(isThemed(token, { theme: "light", targetPropName: "filePath" }) ||
9-
isThemed(token, { theme: "light", targetPropName: "path" }));
6+
export const filterLightColorTokens: Filter["filter"] = (token) => isThemed(token, { theme: "light" });
107

118
export const registerFilterLightColorTokens: RegisterFn = () =>
129
StyleDictionary.registerFilter({

Diff for: packages/calcite-design-tokens/src/build/format/index-file.ts

+16-15
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import prettierSync from "@prettier/sync";
2-
import { Dictionary, FormatFn, FormatFnArguments, TransformedTokens } from "style-dictionary/types";
2+
import { Dictionary, FormatFn, FormatFnArguments } from "style-dictionary/types";
33
import { fileHeader, formattedVariables } from "style-dictionary/utils";
44
import StyleDictionary from "style-dictionary";
55
import { RegisterFn, Stylesheet } from "../types/interfaces.js";
66
import { fromTokens } from "../utils/dictionary.js";
7+
import { isThemed } from "../utils/token-types.js";
8+
import { dark, light } from "../dictionaries/index.js";
79

810
export const registerFormatIndex: RegisterFn = () => {
911
StyleDictionary.registerFormat({
@@ -13,7 +15,7 @@ export const registerFormatIndex: RegisterFn = () => {
1315
};
1416

1517
export const formatIndexFile: FormatFn = async (args) => {
16-
const { dictionary, file, options } = args;
18+
const { file, options } = args;
1719

1820
if (options.fileExtension !== ".css" && options.fileExtension !== ".scss") {
1921
throw new Error("Only .css and .scss file extensions are supported.");
@@ -23,22 +25,21 @@ export const formatIndexFile: FormatFn = async (args) => {
2325
const themes = ["light", "dark"] as const;
2426
const format = options.fileExtension.replace(".", "") as Stylesheet;
2527

26-
const themedTokens = dictionary.allTokens.reduce(
27-
(acc: { light: TransformedTokens; dark: TransformedTokens }, token) => {
28-
if (token.path.includes("light")) {
29-
acc.light[token.name] = token;
30-
} else if (token.path.includes("dark")) {
31-
acc.dark[token.name] = token;
32-
}
33-
return acc;
34-
},
35-
{ light: {}, dark: {} },
36-
);
28+
const darkDictionary = await dark.getPlatformTokens(options.platform, { cache: true });
29+
const lightDictionary = await light.getPlatformTokens(options.platform, { cache: true });
3730

3831
const commonVarFormat = "css";
3932
const varLists = {
40-
light: createVarList(commonVarFormat, fromTokens(themedTokens.light), args),
41-
dark: createVarList(commonVarFormat, fromTokens(themedTokens.dark), args),
33+
light: createVarList(
34+
commonVarFormat,
35+
fromTokens(lightDictionary.allTokens.filter((token) => isThemed(token, { theme: "light" }))),
36+
args,
37+
),
38+
dark: createVarList(
39+
commonVarFormat,
40+
fromTokens(darkDictionary.allTokens.filter((token) => isThemed(token, { theme: "dark" }))),
41+
args,
42+
),
4243
} as const;
4344

4445
const classGroupStrategy = format === "scss" ? "@mixin " : ".";
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import { registerPreprocessorStoreSameValueThemeTokens } from "./store-same-value-theme-tokens.js";
12
import { registerPreprocessorStorePostMergeDictionary } from "./store-post-merge-dictionary.js";
23

34
export function registerPreprocessors(): void {
45
registerPreprocessorStorePostMergeDictionary();
6+
registerPreprocessorStoreSameValueThemeTokens();
57
}
68

9+
export * from "./store-same-value-theme-tokens.js";
710
export * from "./store-post-merge-dictionary.js";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import StyleDictionary from "style-dictionary";
2+
import { DesignToken } from "style-dictionary/types";
3+
import { dark, light } from "../dictionaries/index.js";
4+
import { isThemed } from "../utils/token-types.js";
5+
import { state } from "../shared/state.js";
6+
7+
export function registerPreprocessorStoreSameValueThemeTokens(): void {
8+
StyleDictionary.registerPreprocessor({
9+
name: PreprocessorStoreSameValueThemeTokens,
10+
preprocessor: async (dictionary) => {
11+
const sameValueThemeTokens = light.allTokens
12+
.filter((token) => isThemed(token))
13+
.filter((token, index) => token.value === dark.allTokens[index].value);
14+
const keyToToken = new Map<string, DesignToken>();
15+
16+
sameValueThemeTokens.forEach((token) => {
17+
if (token.key) {
18+
keyToToken.set(token.key, token);
19+
}
20+
});
21+
22+
state.sameValueThemeTokens = keyToToken;
23+
24+
return dictionary;
25+
},
26+
});
27+
}
28+
29+
export const PreprocessorStoreSameValueThemeTokens = "calcite/preprocessor/store-same-value-theme-tokens";
+10-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
const sharedBuildState: any = {
2-
postMergeDictionary: undefined,
3-
} as const;
1+
import { DesignToken, PreprocessedTokens } from "style-dictionary/types";
2+
3+
type State = {
4+
postMergeDictionary: PreprocessedTokens;
5+
sameValueThemeTokens: Map<string, DesignToken>;
6+
};
7+
8+
const sharedBuildState = {
9+
// populated by preprocessors
10+
} as unknown as State;
411

512
export { sharedBuildState as state };

Diff for: packages/calcite-design-tokens/src/build/transforms/value/ensure-type.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import { Filter, ValueTransform } from "style-dictionary/types";
22
import { ArrayValues } from "type-fest";
33
import StyleDictionary from "style-dictionary";
44
import { RegisterFn } from "../../types/interfaces.js";
5+
import { isBreakpoint } from "../../utils/token-types.js";
56

67
const stringValueTokenTypes = ["fontWeight", "dimension", "lineHeight", "opacity", "z-index"] as const;
78
const filterTypes: Filter["filter"] = (token) =>
8-
stringValueTokenTypes.includes(token.type as ArrayValues<typeof stringValueTokenTypes>);
9+
stringValueTokenTypes.includes(token.type as ArrayValues<typeof stringValueTokenTypes>) && !isBreakpoint(token);
910

1011
const transformValueEnsureType: ValueTransform["transform"] = async (token) => {
1112
return `${token.value}`;

Diff for: packages/calcite-design-tokens/src/build/transforms/value/merge-value.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,15 @@ const transformValueMergeValues: ValueTransform["transform"] = async (token, con
2929
);
3030

3131
if (tokenIndex > -1) {
32-
return {
33-
dark: dictionaries.dark.allTokens[tokenIndex].value,
34-
light: dictionaries.light.allTokens[tokenIndex].value,
35-
};
32+
const lightValue = dictionaries.light.allTokens[tokenIndex].value;
33+
const darkValue = dictionaries.dark.allTokens[tokenIndex].value;
34+
35+
if (lightValue !== darkValue) {
36+
return {
37+
light: lightValue,
38+
dark: darkValue,
39+
};
40+
}
3641
}
3742

3843
return token.value;

Diff for: packages/calcite-design-tokens/src/build/transforms/value/px-to-rem.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ function throwSizeError(name: string, value: string, unitType: string) {
3232
throw `Invalid Number: '${name}: ${value}' is not a valid number, cannot transform to '${unitType}' \n`;
3333
}
3434

35-
function isNotBorderOrFixed(token: TransformedToken) {
36-
return !token.path.some((path) => ["border", "fixed"].includes(path));
35+
function isStaticPx(token: TransformedToken) {
36+
return !token.path.some((path) => ["base", "border", "fixed", "px"].includes(path));
3737
}
3838

3939
function filter(token: TransformedToken, options: Config) {
4040
return (
4141
isSource(token) &&
4242
!isBreakpoint(token) &&
43-
isNotBorderOrFixed(token) &&
43+
isStaticPx(token) &&
4444
isDimension(token, options) &&
4545
!isFontRelated(token) &&
4646
!isCornerRadius(token) &&

Diff for: packages/calcite-design-tokens/src/build/utils/dictionary.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { Dictionary, TransformedTokens } from "style-dictionary/types";
1+
import { Dictionary } from "style-dictionary/types";
22
import { convertTokenData } from "style-dictionary/utils";
33

4-
export function fromTokens(tokens: TransformedTokens): Dictionary {
4+
export function fromTokens(tokens: Parameters<typeof convertTokenData>[0]): Dictionary {
55
return {
6-
tokens: tokens,
6+
tokens: convertTokenData(tokens, { output: "object" }),
77
allTokens: convertTokenData(tokens, { output: "array" }),
88
tokenMap: convertTokenData(tokens, { output: "map" }),
99
};

Diff for: packages/calcite-design-tokens/src/build/utils/token-types.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,11 @@ export function isTypography(token: TransformedToken): boolean {
4747

4848
interface IsThemedOptions {
4949
theme?: "light" | "dark";
50-
targetPropName?: keyof Pick<TransformedToken, "filePath" | "path">;
5150
}
5251

53-
export function isThemed(token: TransformedToken, options?: IsThemedOptions): boolean {
54-
const { theme, targetPropName } = options || {};
55-
const targetProp = token[targetPropName ?? "filePath"];
52+
export function isThemed(token: DesignToken, options?: IsThemedOptions): boolean {
53+
const { theme } = options || {};
54+
const targetProp = token.filePath;
5655

5756
return (
5857
token.type === "color" &&

Diff for: packages/calcite-design-tokens/src/config/calcite/dark.ts renamed to packages/calcite-design-tokens/src/config/color/dark.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { expandTypesMap as sdTypes } from "@tokens-studio/sd-transforms";
99
import { transformers, filters, headers, formats } from "../../build/registry/index.js";
1010

1111
const config: Config = {
12-
source: ["src/tokens/semantic/calcite/dark.json"],
13-
include: ["src/tokens/core/[!$]*.json"],
12+
source: ["src/tokens/semantic/color/dark.json"],
13+
include: ["src/tokens/semantic/color/dark.json", "src/tokens/core/[!$]*.json"],
1414
preprocessors: ["tokens-studio"],
1515
platforms: {
1616
scss: {

Diff for: packages/calcite-design-tokens/src/config/calcite/light.ts renamed to packages/calcite-design-tokens/src/config/color/light.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { expandTypesMap as sdTypes } from "@tokens-studio/sd-transforms";
99
import { transformers, filters, headers, formats } from "../../build/registry/index.js";
1010

1111
const config: Config = {
12-
source: ["src/tokens/semantic/calcite/light.json"],
13-
include: ["src/tokens/core/[!$]*.json"],
12+
source: ["src/tokens/semantic/color/light.json"],
13+
include: ["src/tokens/semantic/color/light.json", "src/tokens/core/[!$]*.json"],
1414
preprocessors: ["tokens-studio"],
1515
platforms: {
1616
scss: {

0 commit comments

Comments
 (0)