Skip to content

Commit

Permalink
[HOP-63] Generate Styled System Tokens from StyleDictionary (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexasselin008 authored Nov 6, 2023
1 parent 3cb058c commit c610b68
Show file tree
Hide file tree
Showing 10 changed files with 417 additions and 126 deletions.
2 changes: 2 additions & 0 deletions apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
"unist-util-visit": "5.0.0"
},
"devDependencies": {
"@hopper-ui/tokens": "workspace:*",
"@hopper-ui/components": "workspace:*",
"@storybook/addon-essentials": "7.5.1",
"@storybook/addon-interactions": "7.5.1",
"@storybook/addon-links": "7.5.1",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"doc:storybook": "pnpm --filter=docs storybook",
"doc:build": "pnpm --filter=docs build",
"test": "echo \"no test specified\"",
"build": "pnpm -r --parallel build ",
"build": "pnpm -r build ",
"build:tokens": "pnpm --filter=\"@hopper-ui/tokens\" build",
"changeset": "changeset",
"ci-release": "pnpm build && changeset publish",
Expand Down
1 change: 1 addition & 0 deletions packages/styled-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"react-aria": "3.29.1"
},
"devDependencies": {
"@hopper-ui/tokens": "workspace:*",
"@swc/core": "1.3.95",
"@swc/helpers": "0.5.3",
"@swc/jest": "0.2.29",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* TODO: This file needs to be auto-generated. It is not at the moment
* This file is generated by Style Dictionary. Do not edit directly.
*/

export const DarkSemanticTokens = {
Expand All @@ -8,7 +8,7 @@ export const DarkSemanticTokens = {
"--hop-upsell-icon-weakest": "var(--hop-sunken-treasure-100)",
"--hop-upsell-icon-weak": "var(--hop-sunken-treasure-300)",
"--hop-upsell-border": "var(--hop-sunken-treasure-200)",
"--hop-upsell-surface-hover": "var(--hop-sunken-treasure-600)",
"--hop-upsell-surface-hover": "var(--hop-sunken-treasure-100)",
"--hop-upsell-border-disabled": "var(--hop-sunken-treasure-700)",
"--hop-upsell-icon-active": "var(--hop-sunken-treasure-300)",
"--hop-upsell-surface-weak": "var(--hop-sunken-treasure-800)",
Expand Down Expand Up @@ -82,7 +82,7 @@ export const DarkSemanticTokens = {
"--hop-decorative-option8-surface-strong": "var(--hop-amanita-100)",
"--hop-decorative-option8-surface-hover": "var(--hop-amanita-200)",
"--hop-decorative-option8-text-weak": "var(--hop-amanita-300)",
"--hop-decorative-option8-surface": "var(--hop-amanita-100)",
"--hop-decorative-option8-surface": "var(--hop-amanita-75)",
"--hop-decorative-option8-text": "var(--hop-amanita-900)",
"--hop-decorative-option7-border": "var(--hop-toad-400)",
"--hop-decorative-option7-icon": "var(--hop-toad-900)",
Expand Down Expand Up @@ -253,5 +253,10 @@ export const DarkSemanticTokens = {
"--hop-status-positive-icon": "var(--hop-moss-900)",
"--hop-status-positive-surface-strong": "var(--hop-moss-200)",
"--hop-status-positive-surface": "var(--hop-moss-75)",
"--hop-status-positive-text": "var(--hop-moss-900)"
};
"--hop-status-positive-text": "var(--hop-moss-900)",
"--hop-dataviz-unavailable": "var(--hop-rock-600)",
"--hop-dataviz-unavailable-weak": "var(--hop-rock-400)",
"--hop-dataviz-unavailable-strong": "var(--hop-rock-700)",
"--hop-dataviz-text-onlight": "var(--hop-rock-800)",
"--hop-dataviz-text-ondark": "var(--hop-samoyed)"
};
272 changes: 269 additions & 3 deletions packages/styled-system/src/tokens/generated/light-tokens.ts

Large diffs are not rendered by default.

32 changes: 28 additions & 4 deletions packages/tokens/src/style-dictionary/build.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import StyleDictionary from "style-dictionary";

import { getStyleDictionaryConfig, fontsConfig } from "./config.ts";
import { isDarkTokens } from "./filter/isDarkTokens.ts";
import { fontsConfig, getStyleDictionaryConfig, getStyledSystemTokensConfig } from "./config.ts";
import { isColorType } from "./filter/isColorType.ts";
import { cssDarkMode, customDoc, customJson, fontFace } from "./format/index.ts";
import { isDarkTokens } from "./filter/isDarkTokens.ts";
import { cssDarkMode, customDoc, customJson, customTsTokens, fontFace } from "./format/index.ts";
import { w3cTokenJsonParser } from "./parser/w3c-token-parser.ts";
import { isSizeType, pxToRem, attributeFont } from "./transform/index.ts";
import { attributeFont, isSizeType, pxToRem } from "./transform/index.ts";

const { fileHeader } = StyleDictionary.formatHelpers;

// Filters
StyleDictionary.registerFilter({
Expand Down Expand Up @@ -59,6 +60,23 @@ StyleDictionary.registerFormat({
formatter: customJson
});

StyleDictionary.registerFormat({
name: "custom/ts-tokens",
formatter: ({ dictionary, file }) => {
return fileHeader({ file }) + customTsTokens({ dictionary });
}
});

// File Headers
StyleDictionary.registerFileHeader({
name: "typescript-file-header",
fileHeader: () => {
return [
"This file is generated by Style Dictionary. Do not edit directly."
];
}
});

// Parser
StyleDictionary.registerParser(w3cTokenJsonParser);

Expand All @@ -74,4 +92,10 @@ StyleDictionary.extend(getStyleDictionaryConfig("light")).buildAllPlatforms();
console.log("\n|- 🌙 Building dark mode...");
StyleDictionary.extend(getStyleDictionaryConfig("dark")).buildAllPlatforms();

console.log("\n|- 💅 Building Styled System tokens...");
StyleDictionary.extend(getStyledSystemTokensConfig("light")).buildAllPlatforms();

console.log("\n|- 💅 Building Styled System dark tokens...");
StyleDictionary.extend(getStyledSystemTokensConfig("dark")).buildAllPlatforms();

console.log("\n🚀 Build completed!\n");
40 changes: 36 additions & 4 deletions packages/tokens/src/style-dictionary/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { Config } from "style-dictionary";
import type { Config, File } from "style-dictionary";

const PREFIX = "hop";
const BUILD_PATH = "dist/";
const STORYBOOK_BUILD_PATH = "../src/stories";
const DOCS_BUILD_PATH = "../../../apps/docs";
const STYLED_SYSTEM_BUILD_PATH = "../styled-system/src/";

export const fontsConfig = {
export const fontsConfig: Config = {
"source": ["src/tokens/asset/*.tokens.json"],
"platforms": {
"css-font-face": {
Expand All @@ -28,18 +29,49 @@ export const fontsConfig = {
}
};

export function getStyledSystemTokensConfig(mode: "light" | "dark"): Config {
const isLightMode = mode === "light";

return {
"source": [
"src/tokens/core/*.tokens.json",
`src/tokens/semantic/${mode}/*.tokens.json`
],
"platforms": {
"typescript": {
"transformGroup": "custom/css", // We want the same values and name as the ones shown in css
"buildPath": STYLED_SYSTEM_BUILD_PATH,
"prefix": PREFIX,
"options": {
"fileHeader": "typescript-file-header"
},
"files": [
{
"destination": `tokens/generated/${isLightMode ? "light-tokens" : "dark-semantic-tokens" }.ts`,
"format": "custom/ts-tokens",
"options": {
"outputReferences": true
}
}
]

}
}
};
}

export function getStyleDictionaryConfig(mode: "light" | "dark"): Config {
const isLightMode = mode === "light";

const lightConfig = {
const lightConfig: File = {
"destination": "tokens.css",
"format": "css/variables",
"options": {
"outputReferences": true
}
};

const darkConfig = {
const darkConfig: File = {
"destination": "dark/tokens.css",
"format": "css/dark-mode",
"filter": "mode/dark",
Expand Down
59 changes: 59 additions & 0 deletions packages/tokens/src/style-dictionary/format/custom-ts-tokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { Dictionary, TransformedToken } from "style-dictionary";
import { handleTypes } from "../helpers/index.ts";

export const customTsTokens = function ({ dictionary }: { dictionary: Dictionary }) {
const types = handleTypes(dictionary.allTokens);

function getTokensByFamily(family: string) {
return dictionary.allTokens.filter(token => {
return token.filePath.includes(family);
});
}

let tokens = "";
if (types !== undefined) {
const coreTokens = getTokensByFamily("core");
const semanticTokens = getTokensByFamily("semantic");
const darkSemanticTokens = getTokensByFamily("dark");

const isLightMode = darkSemanticTokens.length === 0;

if (isLightMode) {
tokens += [
formatTokenFamily("CoreTokens", coreTokens, dictionary),
formatTokenFamily("SemanticTokens", semanticTokens, dictionary)
].join("\n");
} else {
tokens += formatTokenFamily("DarkSemanticTokens", darkSemanticTokens, dictionary);
}
}

return tokens;
};


function formatTokenFamily(familyName: string, tokens: TransformedToken[], dictionary:Dictionary) {
const formattedTokens = tokens.map(token => {
const { name, value } = formatTypeScriptToken(token, dictionary);

return ` "${name}": "${value}"`;
}).join(",\n");

return `export const ${familyName} = {\n${formattedTokens}\n};`;
}

function formatTypeScriptToken(token: TransformedToken, dictionary:Dictionary) {
let value = token.value;

if (dictionary.usesReference(token.original.value)) {
const refs = dictionary.getReferences(token.original.value);
refs.forEach(ref => {
value = token.value.replace(ref.value, () => `var(--${ref.name})`);
});
}

return {
name: `--${token.name}`,
value
};
}
1 change: 1 addition & 0 deletions packages/tokens/src/style-dictionary/format/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { cssDarkMode } from "./css-dark-mode.ts";
export { customDoc } from "./custom-doc.ts";
export { customJson } from "./custom-json.ts";
export { customTsTokens } from "./custom-ts-tokens.ts";
export { fontFace } from "./font-face.ts";
Loading

0 comments on commit c610b68

Please sign in to comment.