Skip to content
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

refactor: single CSS file for theme #2204

Merged
merged 7 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/five-apricots-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@digdir/designsystemet-theme': patch
'@digdir/designsystemet': patch
---

refactor: single CSS file for theme
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@
"html-css-class-completion.includeGlobPattern": "packages/css/**/*.{css,html}",
"[github-actions-workflow]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
2 changes: 1 addition & 1 deletion packages/cli/src/tokens/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const makeEntryFile: Action = {

const generateImportUrls = R.pipe(
sortLightmodeFirst,
R.map((file): string => `@import url('./${theme}/${file.toString()}');`),
R.map((file): string => `@import url('${theme}/${file.toString()}');`),
R.join('\n'),
);

Expand Down
45 changes: 29 additions & 16 deletions packages/cli/src/tokens/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as R from 'ramda';
import StyleDictionary from 'style-dictionary';

import * as configs from './configs.js';
import { makeEntryFile } from './utils/entryfile.js';

const { permutateThemes, getConfigs } = configs;

Expand All @@ -26,7 +27,7 @@ const sd = new StyleDictionary();
export async function run(options: Options): Promise<void> {
const tokensDir = options.tokens;
const storefrontOutDir = path.resolve('../../apps/storefront/tokens');
const tokensOutDir = path.resolve(options.out);
const outPath = path.resolve(options.out);

const $themes = JSON.parse(fs.readFileSync(path.resolve(`${tokensDir}/$themes.json`), 'utf-8')) as ThemeObject[];

Expand All @@ -43,9 +44,9 @@ export async function run(options: Options): Promise<void> {
const colormodeThemes = R.filter((val) => val.typography === 'primary', themes);
const semanticThemes = R.filter((val) => val.mode === 'light' && val.typography === 'primary', themes);

const colorModeConfigs = getConfigs(configs.colorModeVariables, tokensOutDir, tokensDir, colormodeThemes);
const semanticConfigs = getConfigs(configs.semanticVariables, tokensOutDir, tokensDir, semanticThemes);
const typographyConfigs = getConfigs(configs.typographyCSS, tokensOutDir, tokensDir, typographyThemes);
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 storefrontConfigs = getConfigs(configs.typescriptTokens, storefrontOutDir, tokensDir, colormodeThemes);

if (typographyConfigs.length > 0) {
Expand All @@ -62,30 +63,30 @@ export async function run(options: Options): Promise<void> {
);
}

if (semanticConfigs.length > 0) {
console.log(`\n🍱 Building ${chalk.green('semantic')}`);
if (colorModeConfigs.length > 0) {
console.log(`\n🍱 Building ${chalk.green('color-mode')}`);

await Promise.all(
semanticConfigs.map(async ({ theme, config, semantic }) => {
console.log(`👷 ${theme} - ${semantic}`);
colorModeConfigs.map(async ({ theme, mode, config }) => {
console.log(`👷 ${theme} - ${mode}`);

const typographyClasses = await sd.extend(config);
const themeVariablesSD = await sd.extend(config);

return typographyClasses.buildAllPlatforms();
return themeVariablesSD.buildAllPlatforms();
}),
);
}

if (colorModeConfigs.length > 0) {
console.log(`\n🍱 Building ${chalk.green('color-mode')}`);
if (semanticConfigs.length > 0) {
console.log(`\n🍱 Building ${chalk.green('semantic')}`);

await Promise.all(
colorModeConfigs.map(async ({ theme, mode, config }) => {
console.log(`👷 ${theme} - ${mode}`);
semanticConfigs.map(async ({ theme, config, semantic }) => {
console.log(`👷 ${theme} - ${semantic}`);

const themeVariablesSD = await sd.extend(config);
const typographyClasses = await sd.extend(config);

return themeVariablesSD.buildAllPlatforms();
return typographyClasses.buildAllPlatforms();
}),
);
}
Expand All @@ -103,4 +104,16 @@ export async function run(options: Options): Promise<void> {
}),
);
}

if (semanticConfigs.length > 0) {
console.log(`\n🍱 Building ${chalk.green('CSS file')}`);

await Promise.all(
semanticConfigs.map(async ({ theme }) => {
console.log(`👷 ${theme}.css`);

return makeEntryFile({ theme, outPath, buildPath: path.resolve(`${outPath}/${theme}`) });
}),
);
}
}
5 changes: 0 additions & 5 deletions packages/cli/src/tokens/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import StyleDictionary from 'style-dictionary';
import type { Config, TransformedToken } from 'style-dictionary/types';
import { outputReferencesFilter } from 'style-dictionary/utils';

import { makeEntryFile } from './actions.js';
import * as formats from './formats/css.js';
import { jsTokens } from './formats/js-tokens.js';
import { nameKebab, sizeRem, typographyShorthand } from './transformers.js';
Expand All @@ -30,8 +29,6 @@ StyleDictionary.registerFormat(formats.colormode);
StyleDictionary.registerFormat(formats.semantic);
StyleDictionary.registerFormat(formats.typography);

StyleDictionary.registerAction(makeEntryFile);

const dsTransformers = [
nameKebab.name,
`ts/resolveMath`,
Expand Down Expand Up @@ -95,7 +92,6 @@ export const colorModeVariables: GetConfig = ({ mode = 'light', outPath, theme }
prefix,
buildPath: `${outPath}/${theme}/`,
transforms: dsTransformers,
actions: [makeEntryFile.name],
files: [
{
destination: `color-mode/${mode}.css`,
Expand Down Expand Up @@ -142,7 +138,6 @@ export const semanticVariables: GetConfig = ({ outPath, theme }) => {
prefix,
buildPath: `${outPath}/${theme}/`,
transforms: dsTransformers,
actions: [makeEntryFile.name],
files: [
{
destination: `semantic.css`,
Expand Down
11 changes: 8 additions & 3 deletions packages/cli/src/tokens/formats/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ export const colormode: Format = {

const content = `{\n${allTokens.map(format).join('\n')}\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`
: `${selector} ${content} ${autoSelectorContent}\n`;

return header + `@layer ${layer} {\n${selector} ${content} ${autoSelectorContent}\n}\n`;
return header + body;
},
};

Expand Down Expand Up @@ -74,8 +77,9 @@ export const semantic: Format = {

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

return header + `@layer ${layer} {\n${selector} ${content}\n}\n`;
return header + body;
},
};

Expand Down Expand Up @@ -193,7 +197,8 @@ export const typography: Format = {
const classes = formattedTokens.classes.join('\n');
const variables = formattedTokens.variables.join('\n');
const content = selector ? `${selector} {\n${variables}\n${classes}\n}` : classes;
const body = R.isNotNil(layer) ? `@layer ${layer} {\n${content}\n}` : content;

return header + `@layer ${layer} {\n${content}\n}\n`;
return header + body;
},
};
44 changes: 44 additions & 0 deletions packages/cli/src/tokens/utils/entryfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import path from 'node:path';
import chalk from 'chalk';
import glob from 'fast-glob';
import fs from 'fs-extra';
import * as R from 'ramda';

const sortLightmodeFirst = R.sortWith<string>([R.descend(R.includes('light')), R.descend(R.includes('secondary'))]);

const header = `@charset "UTF-8";

@layer ds.reset, ds.theme, ds.base, ds.utilities, ds.components;
\n`;

const sortAndConcat = R.pipe(
sortLightmodeFirst,
R.map((file): string => {
try {
const content = fs.readFileSync(file, 'utf-8').toString();
return content;
} catch (e) {
console.error(`Error reading file: ${file}`);
return '';
}
}),
R.join('\n'),
);

type EntryFile = (options: {
outPath: string;
buildPath: string;
theme: string;
}) => Promise<undefined>;

/**
* Creates a CSS entry file that imports base CSS files for a theme
*/
export const makeEntryFile: EntryFile = async ({ outPath, buildPath, theme }) => {
const writePath = `${outPath}/${theme}.css`;

const files = await glob(`**/*`, { cwd: buildPath });
const content = header + sortAndConcat(files.map((file) => `${buildPath}/${file}`));

await fs.writeFile(writePath, content);
};
Loading
Loading