From 092d3029b0ebe06591e706db0a647a25af6b6410 Mon Sep 17 00:00:00 2001 From: Une Sofie Kinn Ekroll Date: Mon, 18 Nov 2024 17:16:56 +0100 Subject: [PATCH] fix(cli): don't require "accent", but generate accent vars if not defined --- package.json | 2 +- packages/cli/bin/designsystemet.ts | 6 -- packages/cli/package.json | 4 +- packages/cli/src/tokens/build.ts | 12 +++- packages/cli/src/tokens/build/configs.ts | 62 +++++++++++++++----- packages/cli/src/tokens/build/formats/css.ts | 13 +++- packages/react/src/colors.ts | 2 +- 7 files changed, 70 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index ca8836103a..32ede37394 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ ], "scripts": { "test": "vitest", - "test:cli": "yarn workspace @digdir/designsystemet test", + "test:cli": "yarn workspace @digdir/designsystemet test --verbose", "test:storybook": "yarn workspace @designsystemet/storybook run-and-test-storybook", "test:coverage": "vitest run --coverage", "storybook": "yarn workspace @designsystemet/storybook dev", diff --git a/packages/cli/bin/designsystemet.ts b/packages/cli/bin/designsystemet.ts index 8915b6475e..5f8b45d618 100644 --- a/packages/cli/bin/designsystemet.ts +++ b/packages/cli/bin/designsystemet.ts @@ -14,7 +14,6 @@ program.name('designsystemet').description('CLI for working with Designsystemet' function makeTokenCommands() { const tokenCmd = createCommand('tokens'); const DEFAULT_TOKENSDIR = './design-tokens'; - const DEFAULT_COLOR = 'accent'; tokenCmd .command('build') @@ -57,11 +56,6 @@ function makeTokenCommands() { }, }; - if (!props.colors.main[DEFAULT_COLOR]) { - console.log(chalk.bold.redBright('ERROR:'), chalk.red(`A main color called "${DEFAULT_COLOR}" is required`)); - process.exit(1); - } - const tokens = createTokens(props); if (write) { diff --git a/packages/cli/package.json b/packages/cli/package.json index 5ec37d4fe9..9e8a30afdf 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -36,8 +36,8 @@ "build": "tsup && yarn build:types", "build:swc": "yarn clean && swc src bin --copy-files -d dist && yarn build:types", "build:types": "tsc --emitDeclarationOnly --declaration", - "test:tokens-create": "yarn designsystemet tokens create -m dominant:#007682 accent:#ff0000 -n #003333 -s support1:#12404f support2:#0054a6 support3:#942977 -w ./test-tokens-create", - "test:tokens-build": "yarn designsystemet tokens build --verbose -t ./test-tokens-create -o ./test-tokens-build", + "test:tokens-create": "yarn designsystemet tokens create -m dominant:#007682 secondary:#ff0000 -n #003333 -s support1:#12404f support2:#0054a6 support3:#942977 -w ./test-tokens-create", + "test:tokens-build": "yarn designsystemet tokens build -t ./test-tokens-create -o ./test-tokens-build", "test:tokens-create-and-build": "rimraf test-tokens-create && rimraf test-tokens-build && yarn test:tokens-create && yarn test:tokens-build", "test": "yarn test:tokens-create-and-build", "clean": "rimraf dist", diff --git a/packages/cli/src/tokens/build.ts b/packages/cli/src/tokens/build.ts index 6db6cced50..d33a6d42d6 100644 --- a/packages/cli/src/tokens/build.ts +++ b/packages/cli/src/tokens/build.ts @@ -11,6 +11,8 @@ import type { BuildConfig, ThemePermutation } from './build/types.js'; import { makeEntryFile } from './build/utils/entryfile.js'; import { processThemeObject } from './build/utils/getMultidimensionalThemes.js'; +export const DEFAULT_COLOR = 'accent'; + type Options = { /** Design tokens path */ tokens: string; @@ -81,11 +83,15 @@ export async function buildTokens(options: Options): Promise { .filter((theme) => R.not(theme.group === 'size' && theme.name !== 'default')); if (!buildOptions.accentColor) { - const firstMainColor = relevant$themes.find((theme) => theme.group === 'main-color'); - buildOptions.accentColor = firstMainColor?.name; + const accentOrFirstMainColor = + relevant$themes.find((theme) => theme.name === DEFAULT_COLOR) || + relevant$themes.find((theme) => theme.group === 'main-color'); + buildOptions.accentColor = accentOrFirstMainColor?.name; } - console.log('default accent color:', buildOptions.accentColor); + if (buildOptions.accentColor !== DEFAULT_COLOR) { + console.log('accent color:', buildOptions.accentColor); + } const buildAndSdConfigs = R.map( (val: BuildConfig) => ({ diff --git a/packages/cli/src/tokens/build/configs.ts b/packages/cli/src/tokens/build/configs.ts index d0246175c6..da4c97f139 100644 --- a/packages/cli/src/tokens/build/configs.ts +++ b/packages/cli/src/tokens/build/configs.ts @@ -4,7 +4,7 @@ import StyleDictionary from 'style-dictionary'; import type { Config as StyleDictionaryConfig, TransformedToken } from 'style-dictionary/types'; import { outputReferencesFilter } from 'style-dictionary/utils'; -import { buildOptions } from '../build.js'; +import { DEFAULT_COLOR, buildOptions } from '../build.js'; import { formats } from './formats/css.js'; import { jsTokens } from './formats/js-tokens.js'; import { nameKebab, resolveMath, sizeRem, typographyName } from './transformers.js'; @@ -70,7 +70,7 @@ export type GetStyleDictionaryConfig = ( options: { outPath?: string; }, -) => StyleDictionaryConfig; +) => StyleDictionaryConfig | { config: StyleDictionaryConfig; permutationOverrides?: Partial }[]; const colorModeVariables: GetStyleDictionaryConfig = ({ mode = 'light', theme }, { outPath }) => { const selector = `${mode === 'light' ? ':root, ' : ''}[data-ds-color-mode="${mode}"]`; @@ -114,7 +114,7 @@ const colorCategoryVariables = const isDefault = color === buildOptions?.accentColor; const selector = `${isDefault ? ':root, ' : ''}[data-color="${color}"]`; - return { + const config: StyleDictionaryConfig = { usesDtcg, preprocessors: ['tokens-studio'], platforms: { @@ -143,6 +143,31 @@ const colorCategoryVariables = }, }, }; + if (isDefault && color !== DEFAULT_COLOR) { + console.log( + `Creating "${DEFAULT_COLOR}" color variables pointing to "${color}", since a color named "${DEFAULT_COLOR}" is not defined`, + ); + // Create a --ds-color-accent-* scale which points to the default color + const defaultColorConfig = R.mergeDeepRight(config, { + platforms: { + css: { + selector: ':root', + files: [ + { + ...config.platforms?.css?.files?.[0], + destination: `color/${DEFAULT_COLOR}.css`, + }, + ], + options: { replaceCategoryWith: DEFAULT_COLOR }, + }, + }, + } satisfies StyleDictionaryConfig); + return [ + { config }, + { config: defaultColorConfig, permutationOverrides: { 'main-color': `${DEFAULT_COLOR} → ${color}` } }, + ]; + } + return config; }; const semanticVariables: GetStyleDictionaryConfig = ({ theme }, { outPath }) => { @@ -308,24 +333,29 @@ export const getConfigsForThemeDimensions = ( const permutations = getMultidimensionalThemes(themes, dimensions); return permutations - .map(({ selectedTokenSets, permutation }) => { + .flatMap(({ selectedTokenSets, permutation }) => { const setsWithPaths = selectedTokenSets.map((x) => `${tokensDir}/${x}.json`); const [source, include] = paritionPrimitives(setsWithPaths); - const config_ = getConfig(permutation, { outPath }); - - const config: StyleDictionaryConfig = { - ...config_, - log: { - ...config_?.log, - verbosity: buildOptions?.verbose ? 'verbose' : 'silent', - }, - source, - include, - }; + const configOrConfigs = getConfig(permutation, { outPath }); + const configs_ = Array.isArray(configOrConfigs) ? configOrConfigs : [{ config: configOrConfigs }]; - return { permutation, config }; + const configs: SDConfigForThemePermutation[] = configs_.map(({ config, permutationOverrides }) => { + return { + permutation: { ...permutation, ...permutationOverrides }, + config: { + ...config, + log: { + ...config?.log, + verbosity: buildOptions?.verbose ? 'verbose' : 'silent', + }, + source, + include, + }, + }; + }); + return configs; }) .sort(); }; diff --git a/packages/cli/src/tokens/build/formats/css.ts b/packages/cli/src/tokens/build/formats/css.ts index df9d479413..edcc3a4dc1 100644 --- a/packages/cli/src/tokens/build/formats/css.ts +++ b/packages/cli/src/tokens/build/formats/css.ts @@ -55,10 +55,16 @@ const colormode: Format = { }, }; +declare module 'style-dictionary/types' { + export interface LocalOptions { + replaceCategoryWith?: string; + } +} + const colorcategory: Format = { name: 'ds/css-colorcategory', format: async ({ dictionary, file, options, platform }) => { - const { outputReferences, usesDtcg } = options; + const { outputReferences, usesDtcg, replaceCategoryWith = '' } = options; const { selector, layer } = platform; const header = await fileHeader({ file }); @@ -72,7 +78,10 @@ const colorcategory: Format = { }), (token: TransformedToken) => ({ ...token, - name: token.name.replace(new RegExp(`-(${colorCategories.main}|${colorCategories.support})-`), '-'), + name: token.name.replace( + new RegExp(`-(${colorCategories.main}|${colorCategories.support})-`), + replaceCategoryWith ? `-${replaceCategoryWith}-` : '-', + ), }), ); diff --git a/packages/react/src/colors.ts b/packages/react/src/colors.ts index 9d683ce3bf..04eec91045 100644 --- a/packages/react/src/colors.ts +++ b/packages/react/src/colors.ts @@ -1,5 +1,5 @@ export type SeverityColors = 'info' | 'success' | 'warning' | 'danger'; -export type CustomColors = 'neutral' | 'accent' | (string & {}); +export type CustomColors = 'neutral' | (string & {}); export type Color = CustomColors | SeverityColors;