Skip to content

Commit

Permalink
feat: split outputs by themeable or not, add semantic layer
Browse files Browse the repository at this point in the history
  • Loading branch information
jorenbroekema committed Mar 12, 2024
1 parent 5830284 commit d0e3bf4
Show file tree
Hide file tree
Showing 19 changed files with 1,228 additions and 433 deletions.
70 changes: 0 additions & 70 deletions build-tokens.cjs

This file was deleted.

99 changes: 99 additions & 0 deletions build-tokens.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import StyleDictionary from "style-dictionary";
import { getReferences, usesReferences } from "style-dictionary/utils";
import { registerTransforms } from "@tokens-studio/sd-transforms";
import { promises } from "node:fs";
import { coreFilter } from "./sd-filters.js";
import {
generateSemanticFiles,
generateComponentFiles,
} from "./sd-file-generators.js";

registerTransforms(StyleDictionary, { casing: "kebab" });

// list of components that we have tokens for, assume the tokenset path for it is tokens/${comp}.json
const components = ["button"];

async function run() {
const $themes = JSON.parse(await promises.readFile("tokens/$themes.json"));

const configs = $themes.map((theme) => ({
__theme__: theme,
source: Object.entries(theme.selectedTokenSets)
.filter(([, val]) => val !== "disabled")
.map(([tokenset]) => `tokens/${tokenset}.json`),
fileHeader: {
autoGeneratedFileHeader: () => {
return [`Do not edit directly, this file was auto-generated`];
},
},
platforms: {
css: {
transformGroup: "tokens-studio",
transforms: ["attribute/themeable"],
files: [
// core tokens, e.g. for application developer
{
destination: "styles/core.css",
format: "css/variables",
filter: coreFilter,
},
// semantic tokens, e.g. for application developer
...generateSemanticFiles(components, theme.name),
// component tokens, e.g. for design system developer
...generateComponentFiles(components, theme.name),
],
},
},
}));

for (const cfg of configs) {
const sd = new StyleDictionary(cfg);

/**
* This transform checks for each token whether that token's value could change
* due to Tokens Studio theming.
* Any tokenset from Tokens Studio marked as "enabled" in the $themes.json is considered
* a set in which any token could change if the theme changes.
* Any token that is inside such a set or is a reference with a token in that reference chain
* that is inside such a set, is considered "themeable",
* which means it could change by theme switching.
*
* This metadata is applied to the token so we can use it as a way of filtering outputs
* later in the "format" stage.
*/
sd.registerTransform({
name: "attribute/themeable",
type: "attribute",
transformer: (token) => {
function isPartOfEnabledSet(token) {
const set = token.filePath
.replace(/^tokens\//g, "")
.replace(/.json$/g, "");
return cfg.__theme__.selectedTokenSets[set] === "enabled";
}

// Set token to themeable if it's part of an enabled set
if (isPartOfEnabledSet(token)) {
return {
themeable: true,
};
}

// Set token to themeable if it's using a reference and inside the reference chain
// any one of them is from a themeable set
if (usesReferences(token.original.value)) {
const refs = getReferences(token.original.value, sd.tokens);
if (refs.some((ref) => isPartOfEnabledSet(ref))) {
return {
themeable: true,
};
}
}
},
});

await sd.cleanAllPlatforms();
await sd.buildAllPlatforms();
}
}
run();
7 changes: 7 additions & 0 deletions button/button.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Do not edit directly, this file was auto-generated
*/

:host {
--button-text-color: #ffffff;
}
11 changes: 11 additions & 0 deletions button/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class TokButton extends adjustAdoptedStylesheetsMixin(LionButtonSubmit) {
...super.styles,
css`
:host {
color: var(--button-text-color);
background: var(--button-bg-color);
border-radius: var(--button-border-radius);
}
Expand All @@ -24,6 +25,16 @@ class TokButton extends adjustAdoptedStylesheetsMixin(LionButtonSubmit) {
constructor() {
super();
this.component = "button";

// This can probably be its own mixin as well...
import(`./button.css`, {
assert: { type: "css" },
}).then(({ default: sheet }) => {
this.shadowRoot.adoptedStyleSheets = [
...this.shadowRoot.adoptedStyleSheets,
sheet,
];
});
}
}

Expand Down
Loading

0 comments on commit d0e3bf4

Please sign in to comment.