Skip to content
Draft
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
14 changes: 8 additions & 6 deletions packages/cli/bin/designsystemet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { createSystemTokenFiles, tokenSetsToFiles } from '../src/tokens/create/f
import { cliOptions, createTokens, tokenSetDimensions } from '../src/tokens/create.js';
import { generateConfigFromTokens } from '../src/tokens/generate-config.js';
import type { OutputFile, Theme } from '../src/tokens/types.js';
import { colorNamesByCategory } from '../src/tokens/utils.js';
import { toColorNames } from '../src/tokens/utils.js';
import { dsfs } from '../src/utils/filesystem.js';
import { parseCreateConfig, readConfigFile } from './config.js';

Expand Down Expand Up @@ -127,19 +127,21 @@ function makeTokenCommands() {

const files: OutputFile[] = [];

// Pick colors from first theme since we have a constraint they should be the same across themes.
const colorNames = toColorNames(config.themes?.[themeNames[0]]?.colors);

for (const [name, themeConfig] of Object.entries(config.themes)) {
const { tokenSets } = await createTokens({ name, ...themeConfig } as Theme);
const { tokenSets } = await createTokens({ name, colorNames, ...themeConfig } as Theme & {
colorNames: string[];
});
files.push(...tokenSetsToFiles(tokenSets));
}

// Pick colors from first theme since we have a constraint they should be the same across themes.
const colors = config.themes?.[themeNames[0]]?.colors ?? { main: {}, support: {} };

files.push(
...(await createSystemTokenFiles({
tokenSetDimensions,
themeNames,
colors: colorNamesByCategory(colors),
colorNames,
})),
);

Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/scripts/update-preview-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createTokens, tokenSetDimensions } from '../tokens/create.js';
import { buildOptions, processPlatform } from '../tokens/process/platform.js';
import { processThemeObject } from '../tokens/process/utils/getMultidimensionalThemes.js';
import type { Theme } from '../tokens/types.js';
import { colorNamesByCategory } from '../tokens/utils.js';
import { toColorNames } from '../tokens/utils.js';
import { dsfs } from '../utils/filesystem.js';

const OUTDIR = '../../internal/components/src/tokens/design-tokens';
Expand All @@ -25,11 +25,11 @@ const toPreviewToken = (tokens: { token: TransformedToken; formatted: string }[]
type PreviewToken = { variable: string; value: string };

export const formatTheme = async (themeConfig: Theme) => {
const { tokenSets } = await createTokens(themeConfig);

const colorNames = toColorNames(themeConfig.colors);
const themeNames = [themeConfig.name];
const colors = colorNamesByCategory(themeConfig.colors);
const $themes = await generate$Themes(tokenSetDimensions, themeNames, colors);

const { tokenSets } = await createTokens({ ...themeConfig, colorNames } as Theme & { colorNames: string[] });
const $themes = await generate$Themes(tokenSetDimensions, themeNames, colorNames);

const processed$themes = $themes.map(processThemeObject);

Expand Down
24 changes: 13 additions & 11 deletions packages/cli/src/tokens/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { generateColorScheme } from './create/generators/primitives/color-scheme
import { generateGlobals } from './create/generators/primitives/globals.js';
import { generateSize, generateSizeGlobal } from './create/generators/primitives/size.js';
import { generateFontSizes, generateTypography } from './create/generators/primitives/typography.js';
import { generateSemanticColors } from './create/generators/semantic/color.js';
import { generateColorModes } from './create/generators/semantic/color-modes.js';
import { generateColorTokens } from './create/generators/semantic/color.js';
import { generateSemanticStyle } from './create/generators/semantic/style.js';
import { generateTheme } from './create/generators/themes/theme.js';
import type { Theme, TokenSet, TokenSetDimensions, TokenSets } from './types.js';
import { toFlatColors } from './utils.js';

export const tokenSetDimensions: TokenSetDimensions = {
colorSchemes: ['dark', 'light'],
Expand All @@ -30,10 +30,13 @@ export const cliOptions = {
},
} as const;

export const createTokens = async (theme: Theme) => {
const { colors, typography, name, borderRadius, overrides } = theme;
export const createTokens = async (theme: Theme & { colorNames: string[] }) => {
const { typography, name, borderRadius, overrides, colorNames } = theme;
const { colorSchemes, sizeModes } = tokenSetDimensions;

const colors = toFlatColors(theme.colors);
const colorTokens = Object.entries(generateColorTokens(colorNames, name));

const tokenSets: TokenSets = new Map([
['primitives/globals', generateGlobals()],
...sizeModes.map((size): [string, TokenSet] => [`primitives/modes/size/${size}`, generateSize(size)]),
Expand All @@ -47,13 +50,12 @@ export const createTokens = async (theme: Theme) => {
...colorSchemes.flatMap((scheme): [string, TokenSet][] => [
[`primitives/modes/color-scheme/${scheme}/${name}`, generateColorScheme(name, scheme, colors, overrides)],
]),
[`themes/${name}`, generateTheme(colors, name, borderRadius)],
['semantic/color', generateSemanticColors(colors, name)],
// maps out semantic modes, ieg 'semantic/modes/main-color/accent', and 'semantic/modes/support-color/brand1'
...Object.entries(generateColorModes(colors, name)).flatMap(([mode, colors]): [string, TokenSet][] =>
Object.entries(colors).map(([key, colorSet]): [string, TokenSet] => [`semantic/modes/${mode}/${key}`, colorSet]),
),
[`semantic/style`, generateSemanticStyle()],
[`themes/${name}`, generateTheme(colorNames, name, borderRadius)],
...colorTokens.map(([colorName, colorSetTokens]): [string, TokenSet] => [
`semantic/color/${colorName}`,
colorSetTokens,
]),
[`semantic/style`, generateSemanticStyle(colorNames)],
]);

return { tokenSets };
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/tokens/create/files.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ColorNamesByCategory, OutputFile, TokenSetDimensions, TokenSets } from '../types.js';
import type { OutputFile, TokenSetDimensions, TokenSets } from '../types.js';
import { generate$Designsystemet } from './generators/$designsystemet.js';
import { generate$Metadata } from './generators/$metadata.js';
import { generate$Themes } from './generators/$themes.js';
Expand All @@ -7,7 +7,7 @@ export const stringify = (data: unknown) => JSON.stringify(data, null, 2);

type CreateTokenFilesOptions = {
tokenSetDimensions: TokenSetDimensions;
colors: ColorNamesByCategory;
colorNames: string[];
themeNames: string[];
};

Expand All @@ -17,15 +17,15 @@ type CreateTokenFilesOptions = {
* `$themes.json` and `$metadata.json` are essential for Token Studio and Style Dictionary to correctly interpret and manage the design tokens.
*/
export const createSystemTokenFiles = async (options: CreateTokenFilesOptions) => {
const { colors, themeNames, tokenSetDimensions } = options;
const { colorNames, themeNames, tokenSetDimensions } = options;

const files: OutputFile[] = [];
const $themesPath = '$themes.json';
const $metadataPath = '$metadata.json';
const $designsystemetPath = '$designsystemet.jsonc';

const $themes = await generate$Themes(tokenSetDimensions, themeNames, colors);
const $metadata = generate$Metadata(tokenSetDimensions, themeNames, colors);
const $themes = await generate$Themes(tokenSetDimensions, themeNames, colorNames);
const $metadata = generate$Metadata(tokenSetDimensions, themeNames, colorNames);
const $designsystemet = generate$Designsystemet();

files.push({ destination: $themesPath, output: stringify($themes) });
Expand Down
7 changes: 3 additions & 4 deletions packages/cli/src/tokens/create/generators/$metadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ColorNamesByCategory, TokenSetDimensions } from '../../types.js';
import type { TokenSetDimensions } from '../../types.js';

type Metadata = {
tokenSetOrder: string[];
Expand All @@ -12,7 +12,7 @@ type Metadata = {
export function generate$Metadata(
tokenSetDimensions: TokenSetDimensions,
themeNames: string[],
colors: ColorNamesByCategory,
colorNames: string[],
): Metadata {
const { colorSchemes, sizeModes } = tokenSetDimensions;
return {
Expand All @@ -28,8 +28,7 @@ export function generate$Metadata(
]),
...themeNames.map((theme) => `themes/${theme}`),
'semantic/color',
...colors.main.map((color) => `semantic/modes/main-color/${color}`),
...colors.support.map((color) => `semantic/modes/support-color/${color}`),
...colorNames.map((color) => `semantic/color/${color}`),
'semantic/style',
],
};
Expand Down
23 changes: 8 additions & 15 deletions packages/cli/src/tokens/create/generators/$themes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { type ThemeObject, TokenSetStatus } from '@tokens-studio/types';

import type { ColorScheme } from '../../../colors/types.js';
import type { ColorNamesByCategory, SizeModes, TokenSetDimensions } from '../../types.js';

const capitalize = (word: string) => word.charAt(0).toUpperCase() + word.slice(1);
import type { SizeModes, TokenSetDimensions } from '../../types.js';

async function createHash(text: string, algo = 'SHA-1') {
const crypto = globalThis.crypto;
Expand Down Expand Up @@ -38,7 +36,7 @@ type ThemeObject_ = ThemeObject & {
export async function generate$Themes(
tokenSetDimensions: TokenSetDimensions,
themeNames: string[],
colors: ColorNamesByCategory,
colorNames: string[],
): Promise<ThemeObject_[]> {
const { colorSchemes, sizeModes } = tokenSetDimensions;
return [
Expand All @@ -47,8 +45,7 @@ export async function generate$Themes(
...generateTypographyGroup(themeNames),
...generateColorSchemesGroup(colorSchemes, themeNames),
generateSemanticGroup(),
...(await generateColorGroup('main', colors.main)),
...(await generateColorGroup('support', colors.support)),
...(await generateColorGroup(colorNames)),
];
}

Expand Down Expand Up @@ -155,7 +152,6 @@ function generateSemanticGroup(): ThemeObject_ {
name: 'Semantic',
selectedTokenSets: {
'semantic/style': TokenSetStatus.ENABLED,
'semantic/color': TokenSetStatus.ENABLED,
'primitives/globals': TokenSetStatus.SOURCE,
},
$figmaCollectionId: 'VariableCollectionId:34811:5976',
Expand All @@ -164,19 +160,16 @@ function generateSemanticGroup(): ThemeObject_ {
};
}

async function generateColorGroup(
group: 'main' | 'support',
colors: ColorNamesByCategory['main'] | ColorNamesByCategory['support'],
): Promise<ThemeObject_[]> {
async function generateColorGroup(colorNames: string[]): Promise<ThemeObject_[]> {
return Promise.all(
colors.map(
colorNames.map(
async (color): Promise<ThemeObject_> => ({
id: await createHash(`${group}-${color}`),
id: await createHash(color),
name: color,
selectedTokenSets: {
[`semantic/modes/${group}-color/${color}`]: TokenSetStatus.ENABLED,
[`semantic/color/${color}`]: TokenSetStatus.ENABLED,
},
group: `${capitalize(group)} color`,
group: `Color`,
}),
),
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as R from 'ramda';
import { baseColors, colorMetadata, dsLinkColor } from '../../../../colors/colorMetadata.js';
import { generateColorScale } from '../../../../colors/index.js';
import type { Color, ColorScheme } from '../../../../colors/types.js';
import type { Color, ColorScheme, CssColor } from '../../../../colors/types.js';
import type { ColorOverrideSchema } from '../../../../config.js';
import type { Colors, Token, TokenSet } from '../../../types.js';
import type { Token, TokenSet } from '../../../types.js';

const generateColor = (colorArray: Color[], overrides?: Record<number, string>): TokenSet => {
const obj: TokenSet = {};
Expand All @@ -22,7 +22,7 @@ const generateColor = (colorArray: Color[], overrides?: Record<number, string>):
export const generateColorScheme = (
themeName: string,
colorScheme: ColorScheme,
colors: Colors,
colors: Record<string, CssColor>,
overrides?: ColorOverrideSchema,
): TokenSet => {
/* Create override mappings for each color */
Expand Down Expand Up @@ -55,25 +55,21 @@ export const generateColorScheme = (
return Object.keys(positionOverrides).length > 0 ? positionOverrides : undefined;
};

const main = R.mapObjIndexed(
(color, colorName) => generateColor(generateColorScale(color, colorScheme), createColorOverrides(colorName)),
colors.main,
);

const support = R.mapObjIndexed(
(color, colorName) => generateColor(generateColorScale(color, colorScheme), createColorOverrides(colorName)),
colors.support,
);
const colorScales = R.mapObjIndexed((color, colorName) => {
if (colorName === 'neutral') {
const neutralColorScale = generateColorScale(colors.neutral, colorScheme);
return generateColor(neutralColorScale, createColorOverrides('neutral'));
}

const neutralColorScale = generateColorScale(colors.neutral, colorScheme);
const neutral = generateColor(neutralColorScale, createColorOverrides('neutral'));
return generateColor(generateColorScale(color, colorScheme), createColorOverrides(colorName));
}, colors);

const baseColorsWithOverrides = {
...baseColors,
...overrides?.severity,
};

const globalColors = R.mapObjIndexed(
const severityColors = R.mapObjIndexed(
(color, colorName) => generateColor(generateColorScale(color, colorScheme), createColorOverrides(colorName)),
baseColorsWithOverrides,
);
Expand All @@ -85,18 +81,16 @@ export const generateColorScheme = (
: undefined;

/* Default focus-inner is position 1 (background-default), focus-outer is position 11 (text-default) */
const defaultFocusInner = neutralColorScale[0].hex;
const defaultFocusOuter = neutralColorScale[10].hex;
const defaultFocusInner = colorScales.neutral[1].$value;
const defaultFocusOuter = colorScales.neutral[11].$value;

const focusInnerOverride = overrides?.focus?.inner?.[colorScheme as 'light' | 'dark'];
const focusOuterOverride = overrides?.focus?.outer?.[colorScheme as 'light' | 'dark'];

return {
[themeName]: {
...main,
...support,
neutral,
...globalColors,
...colorScales,
...severityColors,
link: {
visited: linkOverride || defaultLinkVisited,
},
Expand Down

This file was deleted.

Loading
Loading