Skip to content

Commit

Permalink
Merge pull request #360 from department-of-veterans-affairs/feature/2…
Browse files Browse the repository at this point in the history
…63-narin-theme-setup-tokens

[Feature] Update style-dictionary config to generate themes
  • Loading branch information
narin authored Jun 26, 2024
2 parents 648de61 + 1f2cbe8 commit ca0108e
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 36 deletions.
132 changes: 105 additions & 27 deletions packages/tokens/build.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const StyleDictionary = require('style-dictionary')

/**
* Utils
*/

/** Sort function to alphabetize token objects */
const sortTokensByKey = (obj) => {
const sortedKeys = Object.keys(obj).sort()
const sortedObj = {}
sortedKeys.forEach((key) => {
sortedObj[key] = obj[key]
})

return sortedObj
}

/** Reusable filter function that returns only non-dark-mode tokens */
const filterLight = (token) =>
token.attributes.category.includes('color') &&
!token.name.includes('OnDark') &&
!token.name.includes('-on-dark')

/** Reusable filter function that returns only non-light-mode tokens */
const filterDark = (token) =>
token.attributes.category.includes('color') &&
!token.name.includes('OnLight') &&
!token.name.includes('-on-light')

/** Removes OnDark and OnLight mode suffixes for themes */
const stripMode = (name) => name.replace('OnDark', '').replace('OnLight', '')

/** Reusable reducer function that creates tokens with the mode removed from their name */
const stripModeReducer = (result, token) => {
result[stripMode(token.name)] = token.value
return result
}

/**
* Filters
*/
Expand All @@ -14,26 +50,20 @@ StyleDictionary.registerFilter({
/** Remove tokens that have the dark mode (OnDark/-on-dark) suffix */
StyleDictionary.registerFilter({
name: 'filter/color/light-mode',
matcher: (token) =>
token.attributes.category.includes('color') &&
!token.name.includes('OnDark') &&
!token.name.includes('-on-dark'),
matcher: filterLight,
})

/** Remove tokens that have the light mode (OnLight/-on-light) suffix */
StyleDictionary.registerFilter({
name: 'filter/color/dark-mode',
matcher: (token) =>
token.attributes.category.includes('color') &&
!token.name.includes('OnLight') &&
!token.name.includes('-on-light'),
matcher: filterDark,
})

/**
* Formats
*/

/** Custom format for colors. Exports color tokens as single object */
/** Custom format for colors. Exports all color tokens as single object */
StyleDictionary.registerFormat({
name: 'javascript/es6/vads-colors',
formatter: function (dictionary) {
Expand All @@ -42,20 +72,82 @@ StyleDictionary.registerFormat({
return result
}, {})

return `export const Colors = ${JSON.stringify(sortTokensByKey(colorTokens), null, 2)};`
return `export const colors = ${JSON.stringify(sortTokensByKey(colorTokens), null, 2)};`
},
})

/** Custom format for themes. Filters light and dark mode themes into properties
* and exports them as a single themes object */
StyleDictionary.registerFormat({
name: 'javascript/es6/vads-colors-themes',
formatter: function (dictionary) {
const light = dictionary.allProperties
.filter(filterLight)
.reduce(stripModeReducer, {})

const dark = dictionary.allProperties
.filter(filterDark)
.reduce(stripModeReducer, {})

return (
'export const themes = {\n' +
` light: ${JSON.stringify(sortTokensByKey(light), null, 4)},\n` +
` dark: ${JSON.stringify(sortTokensByKey(dark), null, 4)}\n` +
'}'
)
},
})

/** Custom format to generate index js with exports */
StyleDictionary.registerFormat({
name: 'javascript/es6/vads-module-export',
formatter: function () {
return (
"export { colors } from './colors'\n" +
"export { themes } from './themes'"
)
},
})

/** Creates named type declaration for Colors. Allows for TypeScript autocomplete */
/** Creates named type declaration for colors. Allows for TypeScript autocomplete */
StyleDictionary.registerFormat({
name: 'typescript/es6-declarations/colors',
formatter: function (dictionary) {
let declaration = 'export declare const Colors: {\n'
let declaration = 'export declare const colors: {\n'
dictionary.allProperties.forEach((token) => {
declaration += ` ${token.name}: string;\n`
})
declaration += '}'
return declaration
},
})

/** Creates named type declaration for Themes. Allows for TypeScript autocomplete */
StyleDictionary.registerFormat({
name: 'typescript/es6-declarations/theme',
formatter: function (dictionary) {
let declaration = 'export declare type Theme = {\n'
dictionary.allProperties.forEach((token) => {
declaration += ` ${stripMode(token.name)}: string;\n`
})
declaration += '}\n\n'

declaration +=
'export declare const themes: {\n' +
' light: Theme;\n' +
' dark: Theme;\n' +
'}'
return declaration
},
})

/** Custom format to generate index.d.ts with exports */
StyleDictionary.registerFormat({
name: 'typescript/es6-declarations/module',
formatter: function () {
let declaration = "export * from './types/theme'\n"
declaration += "export * from './types/colors'"

declaration += `}`
return declaration
},
})
Expand Down Expand Up @@ -124,20 +216,6 @@ StyleDictionary.registerTransformGroup({
transforms: ['name/cti/kebab', 'color/hex'],
})

/**
* Utils
*/

const sortTokensByKey = (obj) => {
const sortedKeys = Object.keys(obj).sort()
const sortedObj = {}
sortedKeys.forEach((key) => {
sortedObj[key] = obj[key]
})

return sortedObj
}

const StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/config.js')

StyleDictionaryExtended.buildAllPlatforms()
29 changes: 23 additions & 6 deletions packages/tokens/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,47 @@ module.exports = {
prefix: '',
files: [
{
destination: 'js/index.js',
destination: 'index.d.ts',
format: 'typescript/es6-declarations/module',
},
{
destination: 'js/colors.js',
format: 'javascript/es6/vads-colors',
filter: 'filter/color/is-color',
},
{
destination: 'index.d.ts',
destination: 'js/index.js',
format: 'javascript/es6/vads-module-export',
},
{
destination: 'js/themes.js',
format: 'javascript/es6/vads-colors-themes',
},
{
destination: 'types/colors.d.ts',
format: 'typescript/es6-declarations/colors',
filter: 'filter/color/is-color',
},
{
destination: 'types/theme.d.ts',
format: 'typescript/es6-declarations/theme',
filter: 'filter/color/light-mode',
},
],
},
figma: {
transformGroup: 'figma',
buildPath: './figma/',
files: [
{
destination: `light.json`,
destination: `dark.json`,
format: 'json/dtcg',
filter: 'filter/color/light-mode',
filter: 'filter/color/dark-mode',
},
{
destination: `dark.json`,
destination: `light.json`,
format: 'json/dtcg',
filter: 'filter/color/dark-mode',
filter: 'filter/color/light-mode',
},
],
},
Expand Down
7 changes: 4 additions & 3 deletions packages/tokens/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@department-of-veterans-affairs/mobile-tokens",
"version": "0.12.0",
"version": "0.12.1-alpha.6",
"description": "VA Design System Mobile Token Library",
"main": "dist/js/index.js",
"types": "dist/index.d.ts",
"scripts": {
"tokens:build": "node ./build.js",
"prepack": "node ./build.js",
"tokens:build": "node ./build.js && prettier dist/ --write",
"prepack": "npm run tokens:build",
"publish-package": "npm publish --access public --tolerate-republish"
},
"repository": {
Expand All @@ -31,6 +31,7 @@
"packageManager": "yarn@3.6.1",
"devDependencies": {
"@department-of-veterans-affairs/css-library": "0.7.0",
"prettier": "^3.3.2",
"style-dictionary": "^3.9.2"
}
}
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,7 @@ __metadata:
resolution: "@department-of-veterans-affairs/mobile-tokens@workspace:packages/tokens"
dependencies:
"@department-of-veterans-affairs/css-library": "npm:0.7.0"
prettier: "npm:^3.3.2"
style-dictionary: "npm:^3.9.2"
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -16927,6 +16928,15 @@ __metadata:
languageName: node
linkType: hard

"prettier@npm:^3.3.2":
version: 3.3.2
resolution: "prettier@npm:3.3.2"
bin:
prettier: bin/prettier.cjs
checksum: 39ed27d17f0238da6dd6571d63026566bd790d3d0edac57c285fbab525982060c8f1e01955fe38134ab10f0951a6076da37f015db8173c02f14bc7f0803a384c
languageName: node
linkType: hard

"pretty-bytes@npm:5.6.0":
version: 5.6.0
resolution: "pretty-bytes@npm:5.6.0"
Expand Down

0 comments on commit ca0108e

Please sign in to comment.