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,