Skip to content

Commit

Permalink
docs: add composition tokens for shadows and typographies (#974)
Browse files Browse the repository at this point in the history
* docs: add composition tokens for shadows and typographies
  • Loading branch information
ninamarina authored Oct 18, 2023
1 parent 760deb9 commit 63622eb
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 3 deletions.
27 changes: 24 additions & 3 deletions docs/.vuepress/baseComponents/TokenTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
</template>

<script>
import { getComposedTypographyTokens, getComposedShadowTokens } from '../common/token-utilities';
import CopyButton from './CopyButton.vue';
const FORMAT_MAP = {
Expand All @@ -106,6 +107,19 @@ const CATEGORY_MAP = {
component: ['avatar', 'badge', 'checkbox', 'icon', 'inputs', 'action'],
};
const COMPOSED_TOKENS_CATEGORIES = [
{
category: 'typography',
format: 'CSS',
getTokensFn: getComposedTypographyTokens,
},
{
category: 'shadow',
format: 'CSS',
getTokensFn: getComposedShadowTokens,
},
];
export default {
name: 'TokenTable',
Expand Down Expand Up @@ -134,13 +148,20 @@ export default {
tokensProcessed () {
if (!this.json) return [];
return Object.entries(this.json[this.theme])
const tokens = [];
Object.entries(this.json[this.theme])
.filter(([key, value]) => CATEGORY_MAP[this.category].includes(key.split('/')[0]) && value['css/variables'])
.map(([_, value]) => {
.forEach(([_, value]) => {
const { name, value: tokenValue, description } = value[FORMAT_MAP[this.format]] || {};
const { value: exampleValue } = value['css/variables'];
return { exampleValue, name, tokenValue, description };
tokens.push({ exampleValue, name, tokenValue, description });
});
const composedTokens = [];
if (COMPOSED_TOKENS_CATEGORIES.some(item => item.category === this.category && item.format === this.format)) {
composedTokens.push(...COMPOSED_TOKENS_CATEGORIES
.find(item => item.category === this.category).getTokensFn(this.theme));
}
return [...composedTokens, ...tokens];
},
formatSelectMenuOptions () {
Expand Down
39 changes: 39 additions & 0 deletions docs/.vuepress/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,45 @@ export const DIALTONE_CHANGELOGS = {
},
};

/**
* TECH DEBT: the following constants are duplicated from postcss/constants.js
* There's a ticket to adress this: https://dialpad.atlassian.net/browse/DLT-1288
*/
export const SHADOW_VARIABLES = [
'Small',
'Medium',
'Large',
'ExtraLarge',
'Card',
'Focus',
'FocusInset',
].join('|');

export const TYPOGRAPHY_VARIABLES = [
'Body',
'BodyCompact',
'Headline',
'HeadlineEyebrow',
'HeadlineSoft',
'HeadlineCompact',
'HeadlineCompactSoft',
'Label',
'LabelPlain',
'LabelCompact',
'LabelCompactPlain',
'Helper',
'Code',
].join('|');

export const TYPOGRAPHY_SIZES = [
'Small',
'Base',
'Medium',
'Large',
'ExtraLarge',
'ExtraExtraLarge',
].join('|');

export default {
DIALTONE_CHANGELOGS,
};
104 changes: 104 additions & 0 deletions docs/.vuepress/common/token-utilities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* TECH DEBT: this file is a not exact duplication of postcss/dialtone-generators.js and postcss/helpers.js
* There's a ticket to adress this: https://dialpad.atlassian.net/browse/DLT-1288
*/
import { SHADOW_VARIABLES, TYPOGRAPHY_VARIABLES, TYPOGRAPHY_SIZES } from './constants';
import dialtoneTokensLight from '@dialpad/dialtone-tokens/dist/tokens-light.json';
import dialtoneTokensDark from '@dialpad/dialtone-tokens/dist/tokens-dark.json';

const pascalToKebabCase = (string) => {
return string.split(/(?=[A-Z]|[0-9]{3,}?)/).join('-').toLowerCase();
};

/**
* Extract the box shadow tokens from dialtone-tokens
* based on SHADOW_VARIABLES.
* Performs the name parsing e.g. FocusInset -> focus-inset and
* returns an array containing the shadowName as key and
* the max token index + 1 as value
*
* @returns {Object}
*/
const extractShadows = (mode) => {
const tokens = mode === 'light' ? dialtoneTokensLight : dialtoneTokensDark;
const shadowsRegex = new RegExp(`dtShadow(${SHADOW_VARIABLES})([0-9])(\\w+)`);
return Object.keys(tokens)
.filter(key => shadowsRegex.test(key))
.reduce((shadows, shadow) => {
const [name, index] = shadow
.split(shadowsRegex)
.filter(chunk => !!chunk);

const shadowName = pascalToKebabCase(name);

shadows[shadowName] = Number.parseInt(index) + 1;
return shadows;
}, {});
};

/**
* Extract the typography tokens from dialtone-tokens.
* Performs the name parsing e.g. BodySmall -> body-small and
* returns a set containing typographyNames
*
* @returns {Set}
*/
const extractTypographies = () => {
// eslint-disable-next-line max-len
const typographiesRegex = new RegExp(`dtTypography(${TYPOGRAPHY_VARIABLES})(${TYPOGRAPHY_SIZES})(\\w+)`);
return Object.keys(dialtoneTokensLight)
.filter(key => typographiesRegex.test(key))
.reduce((typographies, typography) => {
const [name, size] = typography
.split(typographiesRegex)
.filter(chunk => !!chunk);

const typographyName = pascalToKebabCase(name);
const typographySize = pascalToKebabCase(size);

typographies.add(`${typographyName}-${typographySize}`);

return typographies;
}, new Set());
};

/**
* Compose typography tokens
*/
export function getComposedTypographyTokens () {
const tokens = [];
const dialtoneTypographies = extractTypographies();
dialtoneTypographies
.forEach(typographyName => {
const composedVar = `--dt-typography-${typographyName}`;
// eslint-disable-next-line max-len
const tokenValue = `var(${composedVar}-font-weight) var(${composedVar}-font-size)/var(${composedVar}-line-height) var(${composedVar}-font-family)`;
tokens.push({ exampleValue: tokenValue['css/variables'], name: composedVar, tokenValue });
});
return tokens;
}

/**
* Compose box shadow tokens
* @param { string } [theme=light]
*/
export function getComposedShadowTokens (theme) {
const tokens = [];
const dialtoneShadows = extractShadows(theme);
Object
.keys(dialtoneShadows)
.forEach(shadowName => {
const shadowVar = `--dt-shadow-${shadowName}`;
const times = dialtoneShadows[shadowName];
const tokenValue = Array(times)
.fill(undefined)
.map((val, i) => {
const shadowNumber = i + 1;
// eslint-disable-next-line max-len
return `var(${shadowVar}-${shadowNumber}-x) var(${shadowVar}-${shadowNumber}-y) var(${shadowVar}-${shadowNumber}-blur) var(${shadowVar}-${shadowNumber}-spread) var(${shadowVar}-${shadowNumber}-color)`;
}).join(', ');

tokens.push({ exampleValue: tokenValue['css/variables'], name: shadowVar, tokenValue });
});
return tokens;
}

0 comments on commit 63622eb

Please sign in to comment.