@openkfw/design-tokens 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/output/web_next_16px/css/kfw-design-tokens.light.css +1 -1
- package/output/web_next_16px/js/kfw-design-tokens.light.d.ts +1 -1
- package/output/web_next_16px/js/kfw-design-tokens.light.js +1 -1
- package/output/web_next_16px/scss/kfw-design-tokens.light.scss +1 -1
- package/output/web_stable_10px/css/kfw-design-tokens.light.css +1 -1
- package/output/web_stable_10px/js/kfw-design-tokens.light.d.ts +1 -1
- package/output/web_stable_10px/js/kfw-design-tokens.light.js +1 -1
- package/output/web_stable_10px/scss/kfw-design-tokens.light.scss +1 -1
- package/package.json +3 -3
- package/sd.config.ts +0 -162
- package/tokens/extended/README.md +0 -15
- package/tokens/extended/build.ts +0 -79
- package/tokens/extended/tokens/tokens.dark.json +0 -21
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openkfw/design-tokens",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "The source of truth for KfW-branded digital products.",
|
|
5
|
-
"main": "sd.config.ts",
|
|
6
5
|
"files": [
|
|
7
6
|
"output",
|
|
8
|
-
"tokens",
|
|
7
|
+
"tokens/tokens.json",
|
|
8
|
+
"tokens/gen-tokens.dark.json5",
|
|
9
9
|
"README.md"
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
package/sd.config.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* KfW Design Tokens https://github.com/openkfw/design-tokens
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) 2025 Artur Sopelnik and contributors, KfW
|
|
5
|
-
*
|
|
6
|
-
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
7
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
8
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import StyleDictionary from "style-dictionary"
|
|
12
|
-
import { Config } from "style-dictionary/types"
|
|
13
|
-
import { formats, logBrokenReferenceLevels, logVerbosityLevels } from "style-dictionary/enums"
|
|
14
|
-
import { RegisterCustom } from "./config"
|
|
15
|
-
|
|
16
|
-
const THEMES = ["light"]
|
|
17
|
-
const PREFIX = "kfw"
|
|
18
|
-
const BASE_PX = {
|
|
19
|
-
next: 16,
|
|
20
|
-
stable: 10
|
|
21
|
-
}
|
|
22
|
-
const CONFIG: Config = {
|
|
23
|
-
usesDtcg: true,
|
|
24
|
-
expand: false,
|
|
25
|
-
log: {
|
|
26
|
-
warnings: "disabled",
|
|
27
|
-
verbosity: logVerbosityLevels.verbose,
|
|
28
|
-
errors: {
|
|
29
|
-
brokenReferences: logBrokenReferenceLevels.throw
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const DEFAULT_SELECTOR = `!(*.${THEMES.join("|*.")})`
|
|
34
|
-
|
|
35
|
-
RegisterCustom(PREFIX)
|
|
36
|
-
|
|
37
|
-
const BUILD_PATH_PREFIX = "output"
|
|
38
|
-
|
|
39
|
-
const createStyleDictionaryConfig = (theme: string, basePxFontSize: number): Config => {
|
|
40
|
-
const isLight = theme === "light"
|
|
41
|
-
const src = isLight ? DEFAULT_SELECTOR : `*.${theme}`
|
|
42
|
-
const isStable = basePxFontSize === 10
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
...CONFIG,
|
|
46
|
-
source: [`tokens/${src}.{json,json5}`],
|
|
47
|
-
platforms: {
|
|
48
|
-
css: {
|
|
49
|
-
basePxFontSize,
|
|
50
|
-
buildPath: `${BUILD_PATH_PREFIX}${isStable ? "/web_stable_10px" : "/web_next_16px"}/css`,
|
|
51
|
-
options: { fileHeader: "kfw-file-header" },
|
|
52
|
-
transformGroup: "custom/css-extended",
|
|
53
|
-
prefix: PREFIX,
|
|
54
|
-
files: [
|
|
55
|
-
{
|
|
56
|
-
destination: `kfw-design-tokens.${theme}.css`,
|
|
57
|
-
format: formats.cssVariables,
|
|
58
|
-
options: {
|
|
59
|
-
selector: (() => {
|
|
60
|
-
// For convenience, the light theme is scoped to :root and will be activated by default when imported.
|
|
61
|
-
const SELECTOR = isLight ? `:root, :host, .${PREFIX}-theme--${theme}` : `:host, .${PREFIX}-theme--${theme}`
|
|
62
|
-
return `${SELECTOR} { color-scheme: ${theme}; }\n\n${SELECTOR}`
|
|
63
|
-
})(),
|
|
64
|
-
outputReferences: false
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
]
|
|
68
|
-
},
|
|
69
|
-
scss: {
|
|
70
|
-
basePxFontSize,
|
|
71
|
-
buildPath: `${BUILD_PATH_PREFIX}${isStable ? "/web_stable_10px" : "/web_next_16px"}/scss`,
|
|
72
|
-
options: { fileHeader: "kfw-file-header" },
|
|
73
|
-
transformGroup: "custom/scss-extended",
|
|
74
|
-
prefix: PREFIX,
|
|
75
|
-
files: [
|
|
76
|
-
{
|
|
77
|
-
destination: `kfw-design-tokens.${theme}.scss`,
|
|
78
|
-
format: formats.scssVariables,
|
|
79
|
-
options: {
|
|
80
|
-
selector: (() => {
|
|
81
|
-
// For convenience, the light theme is scoped to :root and will be activated by default when imported.
|
|
82
|
-
const SELECTOR = isLight ? `:root, :host, .${PREFIX}-theme--${theme}` : `:host, .${PREFIX}-theme--${theme}`
|
|
83
|
-
return `${SELECTOR} { color-scheme: ${theme}; }\n\n${SELECTOR}`
|
|
84
|
-
})(),
|
|
85
|
-
outputReferences: false
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
]
|
|
89
|
-
},
|
|
90
|
-
js: {
|
|
91
|
-
basePxFontSize,
|
|
92
|
-
buildPath: `${BUILD_PATH_PREFIX}${isStable ? "/web_stable_10px" : "/web_next_16px"}/js`,
|
|
93
|
-
options: { fileHeader: "kfw-file-header" },
|
|
94
|
-
transformGroup: "custom/js-extended",
|
|
95
|
-
prefix: PREFIX,
|
|
96
|
-
files: [
|
|
97
|
-
{
|
|
98
|
-
destination: `kfw-design-tokens.${theme}.js`,
|
|
99
|
-
format: formats.javascriptEs6
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
destination: `kfw-design-tokens.${theme}.d.ts`,
|
|
103
|
-
format: formats.typescriptEs6Declarations
|
|
104
|
-
}
|
|
105
|
-
]
|
|
106
|
-
},
|
|
107
|
-
...(!isStable && {
|
|
108
|
-
json: {
|
|
109
|
-
basePxFontSize,
|
|
110
|
-
buildPath: `${BUILD_PATH_PREFIX}/json`,
|
|
111
|
-
transformGroup: "custom/web-extended",
|
|
112
|
-
prefix: PREFIX,
|
|
113
|
-
files: [
|
|
114
|
-
{
|
|
115
|
-
destination: `kfw-design-tokens.${theme}.json`,
|
|
116
|
-
format: formats.json
|
|
117
|
-
}
|
|
118
|
-
]
|
|
119
|
-
},
|
|
120
|
-
figma: {
|
|
121
|
-
basePxFontSize,
|
|
122
|
-
buildPath: `${BUILD_PATH_PREFIX}/figma`,
|
|
123
|
-
transformGroup: "custom/figma-penpot",
|
|
124
|
-
files: [
|
|
125
|
-
{
|
|
126
|
-
destination: `kfw-design-tokens.${theme}.json`,
|
|
127
|
-
format: "json/figma"
|
|
128
|
-
}
|
|
129
|
-
]
|
|
130
|
-
},
|
|
131
|
-
penpot: {
|
|
132
|
-
basePxFontSize,
|
|
133
|
-
buildPath: `${BUILD_PATH_PREFIX}/penpot`,
|
|
134
|
-
transformGroup: "custom/figma-penpot",
|
|
135
|
-
files: [
|
|
136
|
-
{
|
|
137
|
-
destination: `kfw-design-tokens.${theme}.json`,
|
|
138
|
-
format: "json/penpot"
|
|
139
|
-
}
|
|
140
|
-
]
|
|
141
|
-
}
|
|
142
|
-
})
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export default (async function buildThemes() {
|
|
148
|
-
console.log("Build started...")
|
|
149
|
-
console.log("\n==============================================")
|
|
150
|
-
|
|
151
|
-
for (const theme of THEMES) {
|
|
152
|
-
for (const key in BASE_PX) {
|
|
153
|
-
if (Object.prototype.hasOwnProperty.call(BASE_PX, key)) {
|
|
154
|
-
const basePxFontSize = BASE_PX[key as keyof typeof BASE_PX]
|
|
155
|
-
const sd = new StyleDictionary(createStyleDictionaryConfig(theme, basePxFontSize))
|
|
156
|
-
await sd.buildAllPlatforms()
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
console.log("\n==============================================")
|
|
161
|
-
console.log("\nBuild completed!")
|
|
162
|
-
})()
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Style-Dictionary Extended Design Tokens
|
|
2
|
-
|
|
3
|
-
The script `build.ts` generates design tokens (JSON files) based on your reference and the object to be extended. It uses the lodash library to merge the data and json5 to read and write JSON5 files. By using extends, the light version is set as the baseline, as deviating themes like "dark" only change minimally.
|
|
4
|
-
|
|
5
|
-
## 💡 System Requirements
|
|
6
|
-
|
|
7
|
-
- Node.js 22
|
|
8
|
-
- Git
|
|
9
|
-
|
|
10
|
-
## 🚀 Setup
|
|
11
|
-
|
|
12
|
-
1. Select the compatible Node version: `nvm use`
|
|
13
|
-
2. Install dependencies: `npm install`
|
|
14
|
-
3. Build the project: `npm run build`
|
|
15
|
-
- (optional) Build the project with watch: `npm run start`
|
package/tokens/extended/build.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "fs"
|
|
2
|
-
import * as path from "path"
|
|
3
|
-
import JSON5 from "json5"
|
|
4
|
-
import merge from "lodash/merge"
|
|
5
|
-
|
|
6
|
-
const SOURCE_DIRECTORY = path.join(__dirname, "./tokens")
|
|
7
|
-
const OUTPUT_DIRECTORY = path.join(__dirname, "../")
|
|
8
|
-
|
|
9
|
-
const MAPPING: Record<string, string> = {
|
|
10
|
-
"tokens.dark.json": "tokens.json"
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const OUTPUT_FILE_PREFIX = "gen"
|
|
14
|
-
|
|
15
|
-
;(async () => {
|
|
16
|
-
try {
|
|
17
|
-
// Read the files in the directory
|
|
18
|
-
const files = await fs.readdir(SOURCE_DIRECTORY)
|
|
19
|
-
|
|
20
|
-
// Map the files to full paths as JSON
|
|
21
|
-
const jsons = files.map((file) => path.join(SOURCE_DIRECTORY, file)).filter((str) => str.includes(".json"))
|
|
22
|
-
|
|
23
|
-
jsons.map((inputFile) => {
|
|
24
|
-
const fileName = path.basename(inputFile)
|
|
25
|
-
|
|
26
|
-
const mappedValue = getMappedValue(fileName)
|
|
27
|
-
|
|
28
|
-
if (!mappedValue) {
|
|
29
|
-
console.error("Error finding the file to extend. Please check the MAPPING object.")
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const extendedFile = path.join(OUTPUT_DIRECTORY, mappedValue)
|
|
34
|
-
|
|
35
|
-
const fileNameWithoutExtension = path.basename(inputFile, path.extname(inputFile))
|
|
36
|
-
|
|
37
|
-
const outputFile = path.join(OUTPUT_DIRECTORY, `${OUTPUT_FILE_PREFIX ? OUTPUT_FILE_PREFIX + "-" : ""}${fileNameWithoutExtension}.json5`)
|
|
38
|
-
|
|
39
|
-
combineJsonFiles(extendedFile, inputFile, outputFile)
|
|
40
|
-
})
|
|
41
|
-
} catch (err) {
|
|
42
|
-
console.error("Error scanning the directory:", err)
|
|
43
|
-
}
|
|
44
|
-
})()
|
|
45
|
-
|
|
46
|
-
function getMappedValue(key: string): string | undefined {
|
|
47
|
-
if (key in MAPPING) {
|
|
48
|
-
return MAPPING[key]
|
|
49
|
-
}
|
|
50
|
-
return undefined
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function combineJsonFiles(extendedFile: string, inputFile: string, outputFile: string): Promise<void> {
|
|
54
|
-
try {
|
|
55
|
-
const data1 = JSON5.parse(await fs.readFile(extendedFile, "utf8"))
|
|
56
|
-
const data2 = JSON5.parse(await fs.readFile(inputFile, "utf8"))
|
|
57
|
-
|
|
58
|
-
const combinedData = merge({}, data1, data2)
|
|
59
|
-
|
|
60
|
-
const comment = `/**
|
|
61
|
-
* Do not edit directly, this file was auto-generated.
|
|
62
|
-
* By ${inputFile}
|
|
63
|
-
*/\n\n`
|
|
64
|
-
|
|
65
|
-
// Write the combined data to a new JSON5 file
|
|
66
|
-
await fs.writeFile(
|
|
67
|
-
outputFile,
|
|
68
|
-
`${comment}${JSON5.stringify(combinedData, {
|
|
69
|
-
space: 2,
|
|
70
|
-
quote: '"'
|
|
71
|
-
})}\n`,
|
|
72
|
-
"utf8"
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
console.log(`The file ${outputFile} was successfully created.`)
|
|
76
|
-
} catch (error) {
|
|
77
|
-
console.error(`Error processing the files`, error)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"semantic": {
|
|
3
|
-
"color": {
|
|
4
|
-
"$type": "color",
|
|
5
|
-
"fn": {
|
|
6
|
-
"default": { "$value": "{base.color.white.default}" },
|
|
7
|
-
"active": { "$value": "{base.color.white.default}" },
|
|
8
|
-
"border": { "$value": "{base.color.gray.100}" },
|
|
9
|
-
"label": { "$value": "{base.color.gray.100}" }
|
|
10
|
-
},
|
|
11
|
-
"text": {
|
|
12
|
-
"default": { "$value": "{base.color.gray.100}" },
|
|
13
|
-
"on-dark-bg": { "$value": "{base.color.blue.700}" }
|
|
14
|
-
},
|
|
15
|
-
"background": {
|
|
16
|
-
"default": { "$value": "{base.color.black}" },
|
|
17
|
-
"subtle": { "$value": "{base.color.gray.600}" }
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|