-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Add atomic font tokens #540
Changes from 8 commits
3a69d70
7120c39
66da6d1
369ab08
df2a705
3141ebe
92ef31b
bea3972
aa4fda8
951b0b1
a4488d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,13 @@ const stripModeReducer = (result, token) => { | |
return result | ||
} | ||
|
||
/** Filter function to return tokens of category 'font', type from filter, and npm true */ | ||
const fontFilter = (token, fontType) => { | ||
const { category, type, npm } = token.attributes | ||
|
||
return category === 'font' && type === fontType && npm === true | ||
} | ||
|
||
/** | ||
* Filters | ||
*/ | ||
|
@@ -53,6 +60,37 @@ StyleDictionary.registerFilter({ | |
matcher: (token) => token.attributes.category.includes('color'), | ||
}) | ||
|
||
/** Filter to tokens of category 'font', type 'family', and npm true */ | ||
StyleDictionary.registerFilter({ | ||
name: 'filter/font/family-npm', | ||
matcher: (token) => fontFilter(token, 'family'), | ||
}) | ||
|
||
/** Filter to tokens of category 'font', type 'letterSpacing', and npm true */ | ||
StyleDictionary.registerFilter({ | ||
name: 'filter/font/letterSpacing-npm', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest we stick to kebab case instead of mixing camel and kebab There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. Was naming it this way for the source file name, but looking at it holistically using the type name (kebab to follow the raw token name) probably makes more sense. |
||
matcher: (token) => fontFilter(token, 'letter-spacing'), | ||
}) | ||
|
||
/** Filter to tokens of category 'font', type 'size', and npm true */ | ||
StyleDictionary.registerFilter({ | ||
name: 'filter/font/size-npm', | ||
matcher: (token) => fontFilter(token, 'size'), | ||
}) | ||
|
||
/** Filter to tokens of category 'font', type 'line-height', and npm true */ | ||
StyleDictionary.registerFilter({ | ||
name: 'filter/font/lineHeight-npm', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
matcher: (token) => fontFilter(token, 'line-height'), | ||
}) | ||
|
||
/** Remove tokens that do not have 'font' in the category and have figma attribute */ | ||
StyleDictionary.registerFilter({ | ||
name: 'filter/font-figma', | ||
matcher: (token) => | ||
token.attributes.category === 'font' && token.attributes.figma === true, | ||
}) | ||
|
||
/** Remove tokens that have the dark mode (OnDark/-on-dark) suffix */ | ||
StyleDictionary.registerFilter({ | ||
name: 'filter/color/light-mode', | ||
|
@@ -75,16 +113,22 @@ StyleDictionary.registerFilter({ | |
* Formats | ||
*/ | ||
|
||
/** Custom format for colors. Exports all color tokens as single object */ | ||
/** Custom format for basic named export of simple key:value token pairs */ | ||
StyleDictionary.registerFormat({ | ||
name: 'javascript/es6/vads-colors', | ||
formatter: function (dictionary) { | ||
const colorTokens = dictionary.allProperties.reduce((result, token) => { | ||
name: 'javascript/es6/simple-key-value', | ||
formatter: function ({ dictionary, options }) { | ||
const tokens = dictionary.allProperties.reduce((result, token) => { | ||
result[token.name] = token.value | ||
return result | ||
}, {}) | ||
|
||
return `export const colors = ${JSON.stringify(sortTokensByKey(colorTokens), null, 2)};` | ||
const exportName = options.exportName | ||
|
||
if (options.noSort) { | ||
return `export const ${exportName} = ${JSON.stringify(tokens, null, 2)};` | ||
} | ||
|
||
return `export const ${exportName} = ${JSON.stringify(sortTokensByKey(tokens), null, 2)};` | ||
}, | ||
}) | ||
|
||
|
@@ -114,43 +158,94 @@ StyleDictionary.registerFormat({ | |
StyleDictionary.registerFormat({ | ||
name: 'javascript/es6/vads-module-export', | ||
formatter: function () { | ||
return ( | ||
"export { colors } from './colors'\n" + | ||
"export { themes } from './themes'\n" + | ||
"export { spacing } from './spacing'" | ||
) | ||
const files = ['colors', 'font', 'spacing', 'themes'] | ||
let exports = '' | ||
for (const file of files) exports += `export { ${file} } from './${file}'\n` | ||
|
||
return exports | ||
}, | ||
}) | ||
|
||
/** Creates named type declaration for colors. Allows for TypeScript autocomplete */ | ||
/** Custom format to generate font/index.js with exports */ | ||
StyleDictionary.registerFormat({ | ||
name: 'typescript/es6-declarations/colors', | ||
formatter: function (dictionary) { | ||
const sortedTokens = sortTokensByName(dictionary.allTokens) | ||
let declaration = 'export declare const colors: {\n' | ||
sortedTokens.forEach((token) => { | ||
declaration += ` /** ${token.value} */\n` | ||
declaration += ` ${token.name}: string;\n` | ||
}) | ||
declaration += '}' | ||
return declaration | ||
name: 'javascript/es6/fontIndex', | ||
formatter: function () { | ||
const files = ['family', 'letterSpacing', 'lineHeight', 'size'] | ||
let imports = '', | ||
exports = '' | ||
|
||
for (const file of files) imports += `import { ${file} } from './${file}'\n` | ||
exports += 'export const font = {\n' | ||
for (const file of files) exports += `${file},\n` | ||
|
||
return `${imports}\n${exports}}` | ||
}, | ||
}) | ||
|
||
/** Creates named type declaration for spacing. Allows for TypeScript autocomplete */ | ||
/** Custom format to generate font/index.d.ts with exports */ | ||
StyleDictionary.registerFormat({ | ||
name: 'typescript/es6-declarations/spacing', | ||
formatter: function (dictionary) { | ||
let declaration = 'export declare const spacing: {\n' | ||
let allValuesComment = '/**\n * ' | ||
dictionary.allProperties.forEach((token, index) => { | ||
declaration += ` /** Value: ${token.value} */\n` | ||
declaration += ` ${token.name}: number;\n` | ||
allValuesComment += `${index !== 0 ? ' | ' : ''}${token.name.replace('vadsSpace', '')}: ${token.value}` | ||
}) | ||
name: 'typescript/es6-declarations/fontIndex', | ||
formatter: function () { | ||
const files = ['family', 'letterSpacing', 'lineHeight', 'size'] | ||
let imports = '', | ||
exports = '' | ||
|
||
for (const file of files) imports += `import { ${file} } from './${file}'\n` | ||
exports += 'export declare const font: {\n' | ||
for (const file of files) exports += `${file}: typeof ${file},\n` | ||
|
||
return `${imports}\n${exports}}` | ||
}, | ||
}) | ||
|
||
/** Formats basic key-value type declarations exports */ | ||
StyleDictionary.registerFormat({ | ||
name: 'typescript/es6-declarations/simple-key-value', | ||
formatter: function ({ dictionary, options }) { | ||
const tokenTyping = options.tokenTyping || 'number' | ||
let tokens = dictionary.allTokens, | ||
declaration = '', | ||
globalValuesDoc = '/**\n', | ||
docLine = ' * ' | ||
|
||
if (!options.noSort) { | ||
tokens = sortTokensByName(tokens) | ||
} | ||
|
||
if (options.noGlobalDoc) { | ||
globalValuesDoc = '' | ||
} else { | ||
// Add global values doc to the top of the file | ||
for (const token of tokens) { | ||
let tokenDoc = '' | ||
// Shorten token names: | ||
const shortName = token.name | ||
.replace('vads', '') | ||
.replace('FontFamily', '') | ||
.replace('FontLetterSpacing', '') | ||
.replace('FontLineHeight', '') | ||
.replace('FontSize', '') | ||
.replace('Space', '') | ||
|
||
tokenDoc = `${shortName}: \`${token.value}\`` | ||
tokenDoc += token === tokens[tokens.length - 1] ? '' : ' | ' // Add | if not last token | ||
|
||
if (docLine.length + tokenDoc.length > 120) { | ||
globalValuesDoc += docLine + '\n' | ||
docLine = ' * ' | ||
} | ||
docLine += tokenDoc | ||
} | ||
globalValuesDoc += docLine + '\n */\n' | ||
} | ||
|
||
declaration += `export declare const ${options.exportName}: {\n` | ||
for (const token of dictionary.allTokens) { | ||
declaration += ` /** Value: \`${token.value}\` */\n` | ||
declaration += ` ${token.name}: ${tokenTyping};\n` | ||
} | ||
declaration += '}' | ||
allValuesComment += '\n */\n' | ||
return allValuesComment + declaration | ||
return globalValuesDoc + declaration | ||
}, | ||
}) | ||
|
||
|
@@ -179,11 +274,11 @@ StyleDictionary.registerFormat({ | |
StyleDictionary.registerFormat({ | ||
name: 'typescript/es6-declarations/module', | ||
formatter: function () { | ||
let declaration = "export * from './types/theme'\n" | ||
declaration += "export * from './types/colors'\n" | ||
declaration += "export * from './types/spacing'" | ||
const files = ['colors', 'font', 'spacing', 'themes'] | ||
let exports = '' | ||
for (const file of files) exports += `export * from './types/${file}'\n` | ||
|
||
return declaration | ||
return exports | ||
}, | ||
}) | ||
|
||
|
@@ -210,19 +305,27 @@ StyleDictionary.registerFormat({ | |
|
||
if (category.includes('color')) { | ||
return 'color' | ||
} else if (category === 'units') { | ||
return 'dimension' | ||
} else if (category === 'font' && type === 'family') { | ||
return 'fontFamily' | ||
} else if (category === 'font' && type === 'weight') { | ||
return 'fontWeight' | ||
} else if (category === 'font' && type === 'size') { | ||
return 'dimension' | ||
} else if (category === 'spacing') { | ||
return 'number' | ||
} | ||
|
||
return '' | ||
switch (category) { | ||
case 'font': | ||
switch (type) { | ||
case 'family': | ||
case 'style': | ||
return 'string' | ||
case 'letter-spacing': | ||
case 'size': | ||
case 'line-height': | ||
case 'paragraph-spacing': | ||
return 'number' | ||
default: | ||
return '' | ||
} | ||
case 'spacing': | ||
return 'number' | ||
default: | ||
return '' | ||
} | ||
} | ||
|
||
// Format tokens for dtcg | ||
|
@@ -237,28 +340,16 @@ StyleDictionary.registerFormat({ | |
{}, | ||
) | ||
|
||
// Leave spacing tokens sorted by size | ||
if (dictionary.allTokens?.[0].attributes?.category === 'spacing') { | ||
const category = dictionary.allTokens?.[0].attributes?.category | ||
// Leave spacing and font tokens sorted by source (size) | ||
if (category === 'spacing' || category === 'font') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be worth adding a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, did Figma first and didn't figure out the options stuff until later. Updated. |
||
return JSON.stringify(tokens, undefined, 2) + `\n` | ||
} | ||
|
||
return JSON.stringify(sortTokensByKey(tokens), undefined, 2) + `\n` | ||
}, | ||
}) | ||
|
||
/** Custom format for spacing. Exports all spacing tokens as single object */ | ||
StyleDictionary.registerFormat({ | ||
name: 'javascript/es6/vads-spacing', | ||
formatter: function (dictionary) { | ||
const tokens = dictionary.allProperties.reduce((result, token) => { | ||
result[token.name] = token.value | ||
return result | ||
}, {}) | ||
|
||
return `export const spacing = ${JSON.stringify(tokens, null, 2)};` | ||
}, | ||
}) | ||
|
||
/** | ||
* Transform Groups | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, but suggest we follow the
filterX
naming pattern and group with the other filters above.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.