Skip to content

Commit

Permalink
chore: 🔥 Remove autogenerated typography classes (#2429)
Browse files Browse the repository at this point in the history
resolves #2392

- Removed `typography` in name from typography CSS variables (This
touched a lot of files).
- Removed generated CSS classes.
  - Replaced with deconstructed CSS variable for each prop.
- Replicated current classes with new CSS variables to make sure
everything was still working.
- ⚠️ Paragraph typography variants, `short` & `long` needs to be
separate classes to support `@composes` as it colides with other
components `variant`.
  - For example `Button` `variant`.
  - I would think this is a minor tradeoff.
- Saving rewrite of typography classes to new CSS convention for
separate PR as this is big enough.
- Concatenated `base` layer with `utilities` and `typography`


Look at "old" changes in commit
2e0c899
on how `Button` and `Paragraph` can be updated to follow the new
convention.
  • Loading branch information
mimarz authored Sep 19, 2024
1 parent d3229a0 commit c3f9e92
Show file tree
Hide file tree
Showing 44 changed files with 4,511 additions and 4,900 deletions.
310 changes: 248 additions & 62 deletions apps/storefront/tokens/altinn/dark.ts

Large diffs are not rendered by default.

310 changes: 248 additions & 62 deletions apps/storefront/tokens/altinn/light.ts

Large diffs are not rendered by default.

310 changes: 248 additions & 62 deletions apps/storefront/tokens/digdir/dark.ts

Large diffs are not rendered by default.

310 changes: 248 additions & 62 deletions apps/storefront/tokens/digdir/light.ts

Large diffs are not rendered by default.

310 changes: 248 additions & 62 deletions apps/storefront/tokens/portal/dark.ts

Large diffs are not rendered by default.

310 changes: 248 additions & 62 deletions apps/storefront/tokens/portal/light.ts

Large diffs are not rendered by default.

310 changes: 248 additions & 62 deletions apps/storefront/tokens/uutilsynet/dark.ts

Large diffs are not rendered by default.

310 changes: 248 additions & 62 deletions apps/storefront/tokens/uutilsynet/light.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/cli/src/tokens/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export async function buildTokens(options: Options): Promise<void> {

const colorModeConfigs = getConfigs(configs.colorModeVariables, outPath, tokensDir, colormodeThemes);
const semanticConfigs = getConfigs(configs.semanticVariables, outPath, tokensDir, semanticThemes);
const typographyConfigs = getConfigs(configs.typographyCSS, outPath, tokensDir, typographyThemes);
const typographyConfigs = getConfigs(configs.typographyVariables, outPath, tokensDir, typographyThemes);
const storefrontConfigs = getConfigs(configs.typescriptTokens, storefrontOutDir, tokensDir, colormodeThemes);

if (typographyConfigs.length > 0) {
Expand Down
25 changes: 18 additions & 7 deletions packages/cli/src/tokens/build/configs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { register } from '@tokens-studio/sd-transforms';
import { expandTypesMap, register } from '@tokens-studio/sd-transforms';
import type { ThemeObject } from '@tokens-studio/types';
import * as R from 'ramda';
import StyleDictionary from 'style-dictionary';
Expand All @@ -7,7 +7,7 @@ import { outputReferencesFilter } from 'style-dictionary/utils';

import * as formats from './formats/css.js';
import { jsTokens } from './formats/js-tokens.js';
import { nameKebab, sizeRem, typographyShorthand } from './transformers.js';
import { nameKebab, sizeRem, typographyName } from './transformers.js';
import { permutateThemes as permutateThemes_ } from './utils/permutateThemes.js';
import type { PermutatedThemes } from './utils/permutateThemes.js';
import { pathStartsWithOneOf, typeEquals } from './utils/utils.js';
Expand All @@ -25,7 +25,7 @@ const fileHeader = () => [`These files are generated from design tokens defind u

StyleDictionary.registerTransform(sizeRem);
StyleDictionary.registerTransform(nameKebab);
StyleDictionary.registerTransform(typographyShorthand);
StyleDictionary.registerTransform(typographyName);

StyleDictionary.registerFormat(jsTokens);
StyleDictionary.registerFormat(formats.colormode);
Expand All @@ -38,7 +38,7 @@ const dsTransformers = [
'ts/size/px',
sizeRem.name,
'ts/typography/fontWeight',
typographyShorthand.name,
typographyName.name,
'ts/color/modifiers',
'ts/color/css/hexrgba',
'ts/size/lineheight',
Expand Down Expand Up @@ -149,7 +149,7 @@ export const semanticVariables: GetConfig = ({ outPath, theme }) => {
format: formats.semantic.name,
filter: (token) =>
(!token.isSource || isCalculatedToken(token)) &&
!typeEquals(['color', 'fontWeight', 'fontFamily'], token),
!typeEquals(['color', 'fontWeight', 'fontFamily', 'typography'], token),
},
],
options: {
Expand Down Expand Up @@ -200,14 +200,18 @@ export const typescriptTokens: GetConfig = ({ mode = 'unknown', outPath, theme }
};
};

export const typographyCSS: GetConfig = ({ outPath, theme, typography }) => {
export const typographyVariables: GetConfig = ({ outPath, theme, typography }) => {
const selector = `${typography === 'primary' ? ':root, ' : ''}[data-ds-typography="${typography}"]`;
const layer = `ds.theme.typography.${typography}`;

return {
usesDtcg: true,
log: { verbosity: 'silent' },
preprocessors: ['tokens-studio'],
expand: {
include: ['typography'],
typesMap: { ...expandTypesMap, typography: { ...expandTypesMap.typography, letterSpacing: 'dimension' } },
},
platforms: {
css: {
prefix,
Expand All @@ -216,7 +220,14 @@ export const typographyCSS: GetConfig = ({ outPath, theme, typography }) => {
layer,
buildPath: `${outPath}/${theme}/`,
basePxFontSize,
transforms: [nameKebab.name, 'ts/size/px', sizeRem.name, 'ts/size/lineheight', 'ts/typography/fontWeight'],
transforms: [
nameKebab.name,
'ts/size/px',
sizeRem.name,
'ts/size/lineheight',
'ts/typography/fontWeight',
typographyName.name,
],
files: [
{
destination: `typography/${typography}.css`,
Expand Down
126 changes: 17 additions & 109 deletions packages/cli/src/tokens/build/formats/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ export const colormode: Format = {
usesDtcg,
});

const colorSchemeProperty = mode_ === 'dark' || mode_ === 'light' ? `color-scheme: ${mode_};\n` : '';
const colorSchemeProperty = mode_ === 'dark' || mode_ === 'light' ? `\n color-scheme: ${mode_};\n` : '';

const content = `{\n${allTokens.map(format).join('\n')}\n${colorSchemeProperty}}\n`;
const formattedTokens = dictionary.allTokens.map(format).join('\n');
const content = `{\n${formattedTokens}\n${colorSchemeProperty}}\n`;
const autoSelectorContent = ['light', 'dark'].includes(mode_) ? prefersColorScheme(mode_, content) : '';
const body = R.isNotNil(layer)
? `@layer ${layer} {\n${selector} ${content} ${autoSelectorContent}\n}\n`
Expand All @@ -48,7 +49,6 @@ const calculatedVariable = R.pipe(R.split(/:(.*?);/g), (split) => `${split[0]}:
export const semantic: Format = {
name: 'ds/css-semantic',
format: async ({ dictionary, file, options, platform }) => {
const { allTokens } = dictionary;
const { outputReferences, usesDtcg } = options;
const { selector, isCalculatedToken, layer } = platform;

Expand All @@ -61,7 +61,7 @@ export const semantic: Format = {
usesDtcg,
});

const formatTokens = R.map((token: TransformedToken) => {
const formattedTokens = R.map((token: TransformedToken) => {
const originalValue = getValue<string>(token.original);

if (
Expand All @@ -75,50 +75,19 @@ export const semantic: Format = {
}

return format(token);
});
}, dictionary.allTokens);

const formattedVariables = formatTokens(allTokens);
const content = `{\n${formattedVariables.join('\n')}\n}\n`;
const content = `{\n${formattedTokens.join('\n')}\n}\n`;
const body = R.isNotNil(layer) ? `@layer ${layer} {\n${selector} ${content}\n}\n` : `${selector} ${content}\n`;

return header + body;
},
};

type Typgraphy = {
fontWeight: string;
fontSize: string;
lineHeight: number;
fontFamily: string;
};

type ProcessedTokens = { variables: string[]; classes: string[] };

const sortByType = R.sortBy<TransformedToken>((token) => token?.$type === 'typography');
const getVariableName = R.pipe<string[], string[], string, string, string, string>(
R.split(':'),
R.head,
R.defaultTo(''),
R.trim,
(name) => `var(${name})`,
);

const bemify = R.pipe(
(path: string[]) => {
const filteredPath = path.filter((p) => p !== 'typography');
const withPrefix = R.concat([prefix], R.remove(0, 0, filteredPath));
const [rest, last] = R.splitAt(-1, withPrefix);

const className = `${rest.join('-')}--${R.head(last)}`;
return className;
},
R.trim,
R.toLower,
);

const classSelector = R.pipe(R.prop('path'), bemify);
const sortTypographyLast = R.sortWith<TransformedToken>([
R.ascend((token) => (typeEquals('typography')(token) ? 1 : 0)),
// Predicate to filter tokens with .path array that includes both typography and fontFamily
const typographyFontFamilyPredicate = R.allPass([
R.pathSatisfies(R.includes('typography'), ['path']),
R.pathSatisfies(R.includes('fontFamily'), ['path']),
]);

export const typography: Format = {
Expand All @@ -136,74 +105,13 @@ export const typography: Format = {
usesDtcg,
});

const sortedTokens = sortTypographyLast(dictionary.allTokens);

const formattedTokens = R.pipe(
sortByType,
R.reduce<TransformedToken, ProcessedTokens>(
(acc, token) => {
if (typeEquals('fontweight', token)) {
const className = `
.${classSelector(token)} {
font-weight: ${getValue<string>(token)};
}`;

return Object.assign(acc, {
variables: [...acc.variables, format(token)],
classes: [...acc.classes, className],
});
}

if (typeEquals('lineheight', token)) {
const className = `
.${classSelector(token)} {
line-height: ${getValue<string>(token)};
}`;

return Object.assign(acc, {
variables: [...acc.variables, format(token)],
classes: [...acc.classes, className],
});
}

if (typeEquals('typography', token)) {
let references: TransformedToken[] = [];
try {
references = getReferences(getValue<Typgraphy>(token.original), dictionary.tokens);
} catch (error) {
console.error('Error getting references', error);
throw new Error(JSON.stringify(token, null, 2));
}
const fontweight = R.find<TransformedToken>(typeEquals(['fontweight']))(references);
const lineheight = R.find<TransformedToken>(typeEquals(['lineheight']))(references);
const fontsize = R.find<TransformedToken>(typeEquals(['fontsize']))(references);
const letterSpacing = R.find<TransformedToken>(typeEquals(['dimension']))(references);

const fontSizeVar = fontsize ? getVariableName(format(fontsize)) : null;
const fontWeightVar = fontweight ? getVariableName(format(fontweight)) : null;
const lineheightVar = lineheight ? getVariableName(format(lineheight)) : null;
const letterSpacingVar = letterSpacing ? getVariableName(format(letterSpacing)) : null;

const className = `
.${classSelector(token)} {
${fontSizeVar ? `font-size: ${fontSizeVar};` : ''}
${lineheightVar ? `line-height: ${lineheightVar};` : ''}
${fontWeightVar ? `font-weight: ${fontWeightVar};` : ''}
${letterSpacingVar ? `letter-spacing: ${letterSpacingVar};` : ''}
}`;

return Object.assign(acc, { classes: [className, ...acc.classes] });
}

return Object.assign(acc, { variables: [...acc.variables, format(token)] });
},
{ variables: [], classes: [] },
),
)(sortedTokens);

const classes = formattedTokens.classes.join('\n');
const variables = formattedTokens.variables.join('\n');
const content = selector ? `${selector} {\n${variables}\n${classes}\n}` : classes;
console.log('dictionary.allTokens', dictionary.allTokens);

const filteredTokens = R.reject(typographyFontFamilyPredicate, dictionary.allTokens);

const formattedTokens = R.pipe(R.map(format), R.join('\n'))(filteredTokens);

const content = selector ? `${selector} {\n${formattedTokens}\n}` : formattedTokens;
const body = R.isNotNil(layer) ? `@layer ${layer} {\n${content}\n}` : content;

return header + body;
Expand Down
19 changes: 6 additions & 13 deletions packages/cli/src/tokens/build/transformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,13 @@ export const nameKebab: Transform = {
},
};

type Typgraphy = {
fontWeight: string;
fontSize: string;
lineHeight: number;
fontFamily: string;
};

export const typographyShorthand: Transform = {
name: 'typography/shorthand',
type: 'value',
export const typographyName: Transform = {
name: 'name/typography',
type: 'name',
transitive: true,
filter: (token) => typeEquals('typography', token),
// expanded tokens have different type so we match on path instead
filter: (token) => pathStartsWithOneOf(['typography'], token),
transform: (token) => {
const typography = getValue<Typgraphy>(token);
return `${typography.fontWeight} ${typography.fontSize}/${typography.lineHeight} '${typography.fontFamily}'`;
return token.name.replace('-typography', '');
},
};
Loading

0 comments on commit c3f9e92

Please sign in to comment.