mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-12 05:27:07 +00:00
Add foundation for exporting tokens from our color schemes (#2588)
We removed our Figma Tokens/Tokens Studio export a while back when we moved to the theme to ColorSchemes. I'd like to get back to exporting these so we can be working from up to date themes in Figma, especially with the large amount of UI design work we'll be doing in the next few weeks on channels. This PR adds some basic plumbing to start working through the theme/colorScheme and export the parts as tokens. I also discovered that Tokens Studio now publishes their types, so we can use them directly rather than writing our own: https://github.com/tokens-studio/types Pulled those in and started connecting them as well. Running `npm run build-tokens` will export the tokens for each theme to `styles/target/tokens`. Currently only a few element's tokens are exported, will expand this further as time permits. Release Notes: - N/A (No public facing changes)
This commit is contained in:
commit
a75e9faa83
7 changed files with 108 additions and 1 deletions
11
styles/package-lock.json
generated
11
styles/package-lock.json
generated
|
@ -9,6 +9,7 @@
|
|||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@tokens-studio/types": "^0.2.3",
|
||||
"@types/chroma-js": "^2.4.0",
|
||||
"@types/node": "^18.14.1",
|
||||
"ayu": "^8.0.1",
|
||||
|
@ -53,6 +54,11 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tokens-studio/types": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@tokens-studio/types/-/types-0.2.3.tgz",
|
||||
"integrity": "sha512-2KN3V0JPf+Zh8aoVMwykJq29Lsi7vYgKGYBQ/zQ+FbDEmrH6T/Vwn8kG7cvbTmW1JAAvgxVxMIivgC9PmFelNA=="
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
||||
|
@ -271,6 +277,11 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
},
|
||||
"@tokens-studio/types": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@tokens-studio/types/-/types-0.2.3.tgz",
|
||||
"integrity": "sha512-2KN3V0JPf+Zh8aoVMwykJq29Lsi7vYgKGYBQ/zQ+FbDEmrH6T/Vwn8kG7cvbTmW1JAAvgxVxMIivgC9PmFelNA=="
|
||||
},
|
||||
"@tsconfig/node10": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "ts-node ./src/buildThemes.ts",
|
||||
"build-licenses": "ts-node ./src/buildLicenses.ts"
|
||||
"build-licenses": "ts-node ./src/buildLicenses.ts",
|
||||
"build-tokens": "ts-node ./src/buildTokens.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@tokens-studio/types": "^0.2.3",
|
||||
"@types/chroma-js": "^2.4.0",
|
||||
"@types/node": "^18.14.1",
|
||||
"ayu": "^8.0.1",
|
||||
|
|
39
styles/src/buildTokens.ts
Normal file
39
styles/src/buildTokens.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
import { ColorScheme, createColorScheme } from "./common"
|
||||
import { themes } from "./themes"
|
||||
import { slugify } from "./utils/slugify"
|
||||
import { colorSchemeTokens } from "./theme/tokens/colorScheme"
|
||||
|
||||
const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens")
|
||||
|
||||
function clearTokens(tokensDirectory: string) {
|
||||
if (!fs.existsSync(tokensDirectory)) {
|
||||
fs.mkdirSync(tokensDirectory, { recursive: true })
|
||||
} else {
|
||||
for (const file of fs.readdirSync(tokensDirectory)) {
|
||||
if (file.endsWith(".json")) {
|
||||
fs.unlinkSync(path.join(tokensDirectory, file))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeTokens(colorSchemes: ColorScheme[], tokensDirectory: string) {
|
||||
clearTokens(tokensDirectory)
|
||||
|
||||
for (const colorScheme of colorSchemes) {
|
||||
const fileName = slugify(colorScheme.name)
|
||||
const tokens = colorSchemeTokens(colorScheme)
|
||||
const tokensJSON = JSON.stringify(tokens, null, 2)
|
||||
const outPath = path.join(tokensDirectory, `${fileName}.json`)
|
||||
fs.writeFileSync(outPath, tokensJSON)
|
||||
console.log(`- ${outPath} created`)
|
||||
}
|
||||
}
|
||||
|
||||
const colorSchemes: ColorScheme[] = themes.map((theme) =>
|
||||
createColorScheme(theme)
|
||||
)
|
||||
|
||||
writeTokens(colorSchemes, TOKENS_DIRECTORY)
|
12
styles/src/theme/tokens/colorScheme.ts
Normal file
12
styles/src/theme/tokens/colorScheme.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { ColorScheme } from "../colorScheme"
|
||||
import { PlayerTokens, players } from "./players"
|
||||
|
||||
interface ColorSchemeTokens {
|
||||
players: PlayerTokens
|
||||
}
|
||||
|
||||
export function colorSchemeTokens(colorScheme: ColorScheme): ColorSchemeTokens {
|
||||
return {
|
||||
players: players(colorScheme),
|
||||
}
|
||||
}
|
28
styles/src/theme/tokens/players.ts
Normal file
28
styles/src/theme/tokens/players.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { SingleColorToken } from "@tokens-studio/types"
|
||||
import { ColorScheme, Players } from "../../common"
|
||||
import { colorToken } from "./token"
|
||||
|
||||
export type PlayerToken = Record<"selection" | "cursor", SingleColorToken>
|
||||
|
||||
export type PlayerTokens = Record<keyof Players, PlayerToken>
|
||||
|
||||
function buildPlayerToken(colorScheme: ColorScheme, index: number): PlayerToken {
|
||||
|
||||
const playerNumber = index.toString() as keyof Players
|
||||
|
||||
return {
|
||||
selection: colorToken(`player${index}Selection`, colorScheme.players[playerNumber].selection),
|
||||
cursor: colorToken(`player${index}Cursor`, colorScheme.players[playerNumber].cursor),
|
||||
}
|
||||
}
|
||||
|
||||
export const players = (colorScheme: ColorScheme): PlayerTokens => ({
|
||||
"0": buildPlayerToken(colorScheme, 0),
|
||||
"1": buildPlayerToken(colorScheme, 1),
|
||||
"2": buildPlayerToken(colorScheme, 2),
|
||||
"3": buildPlayerToken(colorScheme, 3),
|
||||
"4": buildPlayerToken(colorScheme, 4),
|
||||
"5": buildPlayerToken(colorScheme, 5),
|
||||
"6": buildPlayerToken(colorScheme, 6),
|
||||
"7": buildPlayerToken(colorScheme, 7)
|
||||
})
|
14
styles/src/theme/tokens/token.ts
Normal file
14
styles/src/theme/tokens/token.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { SingleColorToken, TokenTypes } from "@tokens-studio/types"
|
||||
|
||||
export function colorToken(name: string, value: string, description?: string): SingleColorToken {
|
||||
const token: SingleColorToken = {
|
||||
name,
|
||||
type: TokenTypes.COLOR,
|
||||
value,
|
||||
description,
|
||||
}
|
||||
|
||||
if (!token.value || token.value === '') throw new Error("Color token must have a value")
|
||||
|
||||
return token
|
||||
}
|
1
styles/src/utils/slugify.ts
Normal file
1
styles/src/utils/slugify.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export function slugify(t: string): string { return t.toString().toLowerCase().replace(/\s+/g, '-').replace(/[^\w\-]+/g, '').replace(/\-\-+/g, '-').replace(/^-+/, '').replace(/-+$/, '') }
|
Loading…
Reference in a new issue