From 12c501d1cf45151995ae2351965c6a1478a4776a Mon Sep 17 00:00:00 2001
From: Raisa Primerova <48605821+RayRedGoose@users.noreply.github.com>
Date: Thu, 18 Apr 2024 14:38:25 -0600
Subject: [PATCH] chore: Update Style Dictionary transform (#110)
Changes done:
- Colors with alpha has been updated and now shows correct values
- Parser has been updated to handle extensions transform
- `rgba` transform has been updated to replace transparent colors by `transparent` value
- Transform for `flatten-rgba` has been updated to support spaces, percentage alpha
- Filters for `font-family` and `letter-spacing` have been updated to handle new changes in types
- Transform for `font-weight` has been added to handle text variations
- Transform for `line-height` has been added to handle px values
- Shadow tokens documentation added
- Visual tests for color tokens added
[category:Infrastructure]
Release Note:
Bug fixing of generating wrong value for colors with alpha and replacing transparent colors by `transparent` value. New transforms has been added to handle text values of `font-weight` and px values of `line-height`. Transforms for `font-family` and `letter-spacing` have been updated to support different token types, transform for `flatten-rgba` has been updated to handle spaces and percentage alpha.
---
.../stories/system/ColorShadow.stories.mdx | 39 +++++++
.../stories/system/examples/Color/Shadow.tsx | 20 ++++
.../system/visual-testing/Color.stories.tsx | 100 ++++++++++++++++++
packages/canvas-tokens/build.ts | 4 +-
packages/canvas-tokens/tokens/web/sys.json | 6 +-
packages/canvas-tokens/utils/filters/index.ts | 16 ++-
.../utils/spec/transforms.spec.ts | 62 ++++++++++-
.../canvas-tokens/utils/tokenStudioParser.ts | 6 ++
.../utils/transformers/flatRGBAColor.ts | 7 +-
.../canvas-tokens/utils/transformers/index.ts | 15 ++-
10 files changed, 263 insertions(+), 12 deletions(-)
create mode 100644 packages/canvas-tokens-docs/stories/system/ColorShadow.stories.mdx
create mode 100644 packages/canvas-tokens-docs/stories/system/examples/Color/Shadow.tsx
create mode 100644 packages/canvas-tokens-docs/stories/system/visual-testing/Color.stories.tsx
diff --git a/packages/canvas-tokens-docs/stories/system/ColorShadow.stories.mdx b/packages/canvas-tokens-docs/stories/system/ColorShadow.stories.mdx
new file mode 100644
index 0000000..ebcc472
--- /dev/null
+++ b/packages/canvas-tokens-docs/stories/system/ColorShadow.stories.mdx
@@ -0,0 +1,39 @@
+import {Meta, Unstyled} from '@storybook/blocks';
+
+import {ShadowColors} from './examples/Color/Shadow';
+
+
+
+
+
+# System Shadow Color Tokens
+
+System shadow color tokens provide values for box shadow.
+
+## Usage
+
+```ts
+// styles.ts
+import {system} from '@workday/canvas-tokens-web';
+
+const styles = {
+ boxShadow: `0 0 0 var(${system.color.shadow['1']})`,
+};
+```
+
+```css
+// styles.css
+.card-text {
+ boxshadow: 0 0 0 var(--cnvs-sys-color-shadow-1);
+}
+```
+
+---
+
+## Tokens
+
+
+
+---
+
+
diff --git a/packages/canvas-tokens-docs/stories/system/examples/Color/Shadow.tsx b/packages/canvas-tokens-docs/stories/system/examples/Color/Shadow.tsx
new file mode 100644
index 0000000..f99eaa9
--- /dev/null
+++ b/packages/canvas-tokens-docs/stories/system/examples/Color/Shadow.tsx
@@ -0,0 +1,20 @@
+import * as React from 'react';
+import {system} from '@workday/canvas-tokens-web';
+
+import {
+ buildPaletteGroup,
+ ColorGrid,
+ sortSystemColorPalette,
+} from '../../../../components/ColorGrid';
+
+const statusPalettes = buildPaletteGroup(
+ 'system.color.shadow',
+ {
+ default: system.color.shadow.default,
+ '1': system.color.shadow['1'],
+ '2': system.color.shadow['2'],
+ },
+ sortSystemColorPalette
+);
+
+export const ShadowColors = () => ;
diff --git a/packages/canvas-tokens-docs/stories/system/visual-testing/Color.stories.tsx b/packages/canvas-tokens-docs/stories/system/visual-testing/Color.stories.tsx
new file mode 100644
index 0000000..eae01f6
--- /dev/null
+++ b/packages/canvas-tokens-docs/stories/system/visual-testing/Color.stories.tsx
@@ -0,0 +1,100 @@
+import {
+ BackgroundColors,
+ BackgroundAlternateColors,
+ BackgroundMutedColors,
+ BackgroundContrastColors,
+ BackgroundStatusColors,
+} from '../examples/Color/Background';
+import {
+ BorderColors,
+ BorderContrastColors,
+ BorderInputColors,
+ BorderStatusColors,
+} from '../examples/Color/Border';
+import {ForegroundColors, ForegroundStatusColors} from '../examples/Color/Foreground';
+import {IconColors, IconPrimaryColors, IconStatusColors} from '../examples/Color/Icon';
+import {ShadowColors} from '../examples/Color/Shadow';
+import {StaticColors} from '../examples/Color/Static';
+import {TextColors, TextStatusColors} from '../examples/Color/Text';
+
+export default {
+ title: 'Visual Tests/System Tokens/Colors',
+ parameters: {
+ chromatic: {disableSnapshot: false},
+ },
+};
+
+// BACKGROUND COLORS TESTS
+export const Background = {
+ render: BackgroundColors,
+};
+
+export const BackgroundAlternate = {
+ render: BackgroundAlternateColors,
+};
+
+export const BackgroundMuted = {
+ render: BackgroundMutedColors,
+};
+
+export const BackgroundContrast = {
+ render: BackgroundContrastColors,
+};
+
+export const BackgroundStatus = {
+ render: BackgroundStatusColors,
+};
+
+// BORDER COLORS TESTS
+export const Border = {
+ render: BorderColors,
+};
+export const BorderContrast = {
+ render: BorderContrastColors,
+};
+export const BorderInput = {
+ render: BorderInputColors,
+};
+export const BorderStatus = {
+ render: BorderStatusColors,
+};
+
+// FOREGROUND COLORS TESTS
+
+export const Foreground = {
+ render: ForegroundColors,
+};
+export const ForegroundStatus = {
+ render: ForegroundStatusColors,
+};
+
+// ICON COLORS TESTS
+
+export const Icon = {
+ render: IconColors,
+};
+export const IconPrimary = {
+ render: IconPrimaryColors,
+};
+export const IconStatus = {
+ render: IconStatusColors,
+};
+
+// SHADOW COLORS TESTS
+export const Shadow = {
+ render: ShadowColors,
+};
+
+// STATIC COLORS TESTS
+export const Static = {
+ render: StaticColors,
+};
+
+// TEXT COLORS TESTS
+export const Text = {
+ render: TextColors,
+};
+
+export const TextStatus = {
+ render: TextStatusColors,
+};
diff --git a/packages/canvas-tokens/build.ts b/packages/canvas-tokens/build.ts
index 409ab92..d24c927 100644
--- a/packages/canvas-tokens/build.ts
+++ b/packages/canvas-tokens/build.ts
@@ -113,8 +113,10 @@ StyleDictionary.registerTransformGroup({
'value/hex-to-rgba',
'value/wrapped-font-family',
'value/math',
- 'value/spacing-rem',
+ 'value/letter-spacing/px2rem',
'value/flatten-rgba',
+ 'value/font-weight/lower-case',
+ 'value/line-height/px2rem',
],
});
diff --git a/packages/canvas-tokens/tokens/web/sys.json b/packages/canvas-tokens/tokens/web/sys.json
index 34f456c..ad0cf17 100644
--- a/packages/canvas-tokens/tokens/web/sys.json
+++ b/packages/canvas-tokens/tokens/web/sys.json
@@ -8,7 +8,7 @@
"description": "Main background color\n"
},
"transparent": {
- "value": "rgba({palette.french-vanilla.100}, 0)",
+ "value": "rgba({palette.french-vanilla.100},0)",
"type": "color",
"description": "Transparent background"
},
@@ -18,7 +18,7 @@
"description": "Overlay background"
},
"translucent": {
- "value": "rgba({palette.black-pepper.600} ,{opacity.500})",
+ "value": "rgba({palette.black-pepper.600},{opacity.500})",
"type": "color",
"description": "Tooltip, Status Indicator"
},
@@ -448,7 +448,7 @@
}
},
"transparent": {
- "value": "rgba({color.static.white}, 0%)",
+ "value": "rgba({color.static.white},0)",
"type": "color",
"description": "Transparent"
},
diff --git a/packages/canvas-tokens/utils/filters/index.ts b/packages/canvas-tokens/utils/filters/index.ts
index 7859789..5059254 100644
--- a/packages/canvas-tokens/utils/filters/index.ts
+++ b/packages/canvas-tokens/utils/filters/index.ts
@@ -4,8 +4,12 @@ export const isBaseShadow: Matcher = ({path: [level], type}) => {
return level === 'base' && type === 'boxShadow';
};
-export const isBaseFontFamily: Matcher = ({type, path: [level]}) => {
- return level === 'base' && type === 'fontFamilies';
+export const isBaseFontFamily: Matcher = ({path: [level, category]}) => {
+ return level === 'base' && category === 'font-family';
+};
+
+export const isBaseFontWeight: Matcher = ({type, path: [level, category]}) => {
+ return level === 'base' && category === 'font-weight' && type === 'text';
};
export const isBorder: Matcher = ({type, path: [level]}) => {
@@ -16,8 +20,12 @@ export const isHexColor: Matcher = ({value}) => {
return /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/.test(value);
};
-export const isLetterSpacing: Matcher = ({type}) => {
- return type === 'letterSpacing';
+export const isLetterSpacing: Matcher = ({path: [level, category]}) => {
+ return level === 'base' && category === 'letter-spacing';
+};
+
+export const isPxLineHeight: Matcher = ({type, path: [level, category]}) => {
+ return level === 'base' && category === 'line-height' && type === 'number';
};
export const isSysColor: Matcher = ({original}) => {
diff --git a/packages/canvas-tokens/utils/spec/transforms.spec.ts b/packages/canvas-tokens/utils/spec/transforms.spec.ts
index 2ac521e..9659605 100644
--- a/packages/canvas-tokens/utils/spec/transforms.spec.ts
+++ b/packages/canvas-tokens/utils/spec/transforms.spec.ts
@@ -34,6 +34,46 @@ describe('transforms', () => {
expect(result).toBe(expected);
});
+ it('should handle percentage alpha in rgba', () => {
+ const result = transforms['value/flatten-rgba'].transformer(
+ {...defaultToken, value: 'rgba(rgba(0,0,0,1),50%)'},
+ defaultOptions
+ );
+ const expected = 'rgba(0,0,0,0.5)';
+
+ expect(result).toBe(expected);
+ });
+
+ it('should handle space before opacity', () => {
+ const result = transforms['value/flatten-rgba'].transformer(
+ {...defaultToken, value: 'rgba(rgba(0,0,0,1), 50%)'},
+ defaultOptions
+ );
+ const expected = 'rgba(0,0,0,0.5)';
+
+ expect(result).toBe(expected);
+ });
+
+ it('should handle space before opacity', () => {
+ const result = transforms['value/flatten-rgba'].transformer(
+ {...defaultToken, value: 'rgba(rgba(0,0,0,1),50)'},
+ defaultOptions
+ );
+ const expected = 'rgba(0,0,0,0.5)';
+
+ expect(result).toBe(expected);
+ });
+
+ it('should handle space before opacity', () => {
+ const result = transforms['value/flatten-rgba'].transformer(
+ {...defaultToken, value: 'rgba(rgba(0,0,0,1),.64)'},
+ defaultOptions
+ );
+ const expected = 'rgba(0,0,0,0.64)';
+
+ expect(result).toBe(expected);
+ });
+
it('should turn sys color to correct rgba', () => {
const result = transforms['value/flatten-rgba'].transformer(
{
@@ -70,7 +110,7 @@ describe('transforms', () => {
});
it('should convert letter spacing values from px to rem', () => {
- const result = transforms['value/spacing-rem'].transformer(
+ const result = transforms['value/letter-spacing/px2rem'].transformer(
{...defaultToken, value: '0.4'},
defaultOptions
);
@@ -79,6 +119,26 @@ describe('transforms', () => {
expect(result).toBe(expected);
});
+ it('should convert line height values from px to rem', () => {
+ const result = transforms['value/line-height/px2rem'].transformer(
+ {...defaultToken, value: '16'},
+ defaultOptions
+ );
+ const expected = '1rem';
+
+ expect(result).toBe(expected);
+ });
+
+ it('should change font weight value to lower case', () => {
+ const result = transforms['value/font-weight/lower-case'].transformer(
+ {...defaultToken, value: 'Bold'},
+ defaultOptions
+ );
+ const expected = 'bold';
+
+ expect(result).toBe(expected);
+ });
+
it('should resolve math expression for base tokens', () => {
const result = transforms['value/math'].transformer(
{
diff --git a/packages/canvas-tokens/utils/tokenStudioParser.ts b/packages/canvas-tokens/utils/tokenStudioParser.ts
index 3698eb3..a7fcdca 100644
--- a/packages/canvas-tokens/utils/tokenStudioParser.ts
+++ b/packages/canvas-tokens/utils/tokenStudioParser.ts
@@ -138,6 +138,12 @@ const mapObjectContent = (fn: (token: DesignToken) => DesignToken, obj: DesignTo
const transformExtensions = (token: DesignToken) => {
if (token['$extensions']) {
+ const {modify} = token['$extensions']['studio.tokens'];
+
+ if (modify && modify.type === 'alpha') {
+ token.value = `rgba(${token.value},${modify.value})`;
+ }
+
delete token['$extensions'];
}
};
diff --git a/packages/canvas-tokens/utils/transformers/flatRGBAColor.ts b/packages/canvas-tokens/utils/transformers/flatRGBAColor.ts
index ed58470..132a854 100644
--- a/packages/canvas-tokens/utils/transformers/flatRGBAColor.ts
+++ b/packages/canvas-tokens/utils/transformers/flatRGBAColor.ts
@@ -8,12 +8,15 @@ import {DesignToken} from 'style-dictionary';
* @returns updated token value
*/
export const flatRGBAColor = ({value}: DesignToken): string => {
- const rgba = value.replace(/rgba\((rgba\([,0-9]*)\),([.0-9]*)\)/g, (a: string, b: string) => {
+ const rgba = value.replace(/rgba\((rgba\([,0-9]*)\),([\s.0-9%]*)\)/g, (a: string, b: string) => {
const [alpha] = a.slice(0, -1).split(',').reverse();
+ const alphaNumber: number = parseFloat(alpha);
+ const alphaResult = alpha.includes('%') || alphaNumber > 1 ? alphaNumber / 100 : alphaNumber;
+
const innerRgb = b.replace(/rgba\(([^}]+)/g, (__: string, c: string) =>
c.split(',').slice(0, 3).toString()
);
- return `rgba(${innerRgb},${alpha})`;
+ return alphaResult === 0 ? 'transparent' : `rgba(${innerRgb},${alphaResult})`;
});
return rgba;
diff --git a/packages/canvas-tokens/utils/transformers/index.ts b/packages/canvas-tokens/utils/transformers/index.ts
index 5747462..24ec5df 100644
--- a/packages/canvas-tokens/utils/transformers/index.ts
+++ b/packages/canvas-tokens/utils/transformers/index.ts
@@ -21,6 +21,19 @@ export const transforms: Record = {
matcher: filter.isBaseShadow,
transformer: flatShadow,
},
+ // transform function that changes the shadow object as value to the single line string
+ 'value/font-weight/lower-case': {
+ type: 'value',
+ transitive: true,
+ matcher: filter.isBaseFontWeight,
+ transformer: ({value}) => value.toLowerCase(),
+ },
+ 'value/line-height/px2rem': {
+ type: 'value',
+ transitive: true,
+ matcher: filter.isPxLineHeight,
+ transformer: ({value}) => `${parseFloat(value) / 16}rem`,
+ },
// transform function that removes doubled rgba for tokens with references
'value/flatten-rgba': {
type: 'value',
@@ -48,7 +61,7 @@ export const transforms: Record = {
transformer: ({value}) => `"${value}"`,
},
// transform function that adds em to letter spacing values
- 'value/spacing-rem': {
+ 'value/letter-spacing/px2rem': {
type: 'value',
transitive: true,
matcher: filter.isLetterSpacing,