diff --git a/MIGRATION.md b/MIGRATION.md index e968c83f..aeab03ad 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -50,7 +50,32 @@ In this version, significant updates have been made to color tokens, including m #### JS ``` -TBC +### Brand colors +brandColor.grey750 +brandColor.violet300 +brandColor.white010 + +### Theme colors +colors.primary.disabled +colors.secondary.default +colors.secondary.alternative +colors.secondary.muted +colors.secondary.inverse +colors.secondary.disabled +colors.error.disabled +colors.warning.alternative +colors.warning.disabled +colors.success.alternative +colors.success.disabled +colors.info.alternative +colors.info.disabled +colors.networks.goerli.default +colors.networks.goerli.inverse +colors.networks.localhost.default +colors.networks.localhost.inverse +colors.networks.sepolia.default +colors.networks.sepolia.inverse + ``` ### Changed @@ -77,7 +102,20 @@ TBC #### JS ``` -TBC +### Brand colors +brandColor.grey030 modified to brandColor.grey025 +brandColor.grey040 modified to brandColor.grey050 +brandColor.blue000 modified to brandColor.blue025 +brandColor.green000 modified to brandColor.green025 +brandColor.red000 modified to brandColor.red025 +brandColor.yellow000 modified to brandColor.yellow025 +brandColor.orange000 modified to brandColor.orange025 +brandColor.white000 modified to brandColor.white +brandColor.black000 modified to brandColor.black + +### Theme colors +colors.primary.shadow modified to colors.shadow.primary +colors.error.shadow modified to colors.shadow.primary ``` ## From version 2.1.1 to 3.0.0 diff --git a/src/js/brandColor/brandColor.test.ts b/src/js/brandColor/brandColor.test.ts index 932e3c78..4be1c64e 100644 --- a/src/js/brandColor/brandColor.test.ts +++ b/src/js/brandColor/brandColor.test.ts @@ -1,410 +1,29 @@ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ import { brandColor } from './brandColor'; -const designTokens = require('../../figma/tokens.json'); +const designTokens = require('../../figma/brandColors.json'); describe('Brand Color', () => { - describe('White', () => { - it('js tokens for white000 matches figma tokens white000', () => { - expect(brandColor.white000).toStrictEqual( - designTokens.global.brandColors.white.white000.value.toLowerCase(), - ); - }); - - it('js tokens for white010 matches figma tokens white010', () => { - expect(brandColor.white010).toStrictEqual( - designTokens.global.brandColors.white.white010.value.toLowerCase(), - ); - }); - }); - - describe('Black', () => { - it('js tokens for black000 matches figma tokens black000', () => { - expect(brandColor.black000).toStrictEqual( - designTokens.global.brandColors.black.black000.value.toLowerCase(), - ); - }); - }); - - describe('Grey', () => { - it('js tokens for grey030 matches figma tokens grey030', () => { - expect(brandColor.grey030).toStrictEqual( - designTokens.global.brandColors.grey.grey030.value.toLowerCase(), - ); - }); - - it('js tokens for grey040 matches figma tokens grey040', () => { - expect(brandColor.grey040).toStrictEqual( - designTokens.global.brandColors.grey.grey040.value.toLowerCase(), - ); - }); - - it('js tokens for grey100 matches figma tokens grey100', () => { - expect(brandColor.grey100).toStrictEqual( - designTokens.global.brandColors.grey.grey100.value.toLowerCase(), - ); - }); - - it('js tokens for grey200 matches figma tokens grey200', () => { - expect(brandColor.grey200).toStrictEqual( - designTokens.global.brandColors.grey.grey200.value.toLowerCase(), - ); - }); - - it('js tokens for grey300 matches figma tokens grey300', () => { - expect(brandColor.grey300).toStrictEqual( - designTokens.global.brandColors.grey.grey300.value.toLowerCase(), - ); - }); - - it('js tokens for grey400 matches figma tokens grey400', () => { - expect(brandColor.grey400).toStrictEqual( - designTokens.global.brandColors.grey.grey400.value.toLowerCase(), - ); - }); - - it('js tokens for grey500 matches figma tokens grey500', () => { - expect(brandColor.grey500).toStrictEqual( - designTokens.global.brandColors.grey.grey500.value.toLowerCase(), - ); - }); - - it('js tokens for grey600 matches figma tokens grey600', () => { - expect(brandColor.grey600).toStrictEqual( - designTokens.global.brandColors.grey.grey600.value.toLowerCase(), - ); - }); - - it('js tokens for grey700 matches figma tokens grey700', () => { - expect(brandColor.grey700).toStrictEqual( - designTokens.global.brandColors.grey.grey700.value.toLowerCase(), - ); - }); - - it('js tokens for grey750 matches figma tokens grey750', () => { - expect(brandColor.grey750).toStrictEqual( - designTokens.global.brandColors.grey.grey750.value.toLowerCase(), - ); - }); - - it('js tokens for grey800 matches figma tokens grey800', () => { - expect(brandColor.grey800).toStrictEqual( - designTokens.global.brandColors.grey.grey800.value.toLowerCase(), - ); - }); - - it('js tokens for grey900 matches figma tokens grey900', () => { - expect(brandColor.grey900).toStrictEqual( - designTokens.global.brandColors.grey.grey900.value.toLowerCase(), - ); - }); - }); - - describe('Blue', () => { - it('js tokens for blue000 matches figma tokens blue000', () => { - expect(brandColor.blue000).toStrictEqual( - designTokens.global.brandColors.blue.blue000.value.toLowerCase(), - ); - }); - - it('js tokens for blue100 matches figma tokens blue100', () => { - expect(brandColor.blue100).toStrictEqual( - designTokens.global.brandColors.blue.blue100.value.toLowerCase(), - ); - }); - - it('js tokens for blue200 matches figma tokens blue200', () => { - expect(brandColor.blue200).toStrictEqual( - designTokens.global.brandColors.blue.blue200.value.toLowerCase(), - ); - }); - - it('js tokens for blue300 matches figma tokens blue300', () => { - expect(brandColor.blue300).toStrictEqual( - designTokens.global.brandColors.blue.blue300.value.toLowerCase(), - ); - }); - - it('js tokens for blue400 matches figma tokens blue400', () => { - expect(brandColor.blue400).toStrictEqual( - designTokens.global.brandColors.blue.blue400.value.toLowerCase(), - ); - }); - - it('js tokens for blue500 matches figma tokens blue500', () => { - expect(brandColor.blue500).toStrictEqual( - designTokens.global.brandColors.blue.blue500.value.toLowerCase(), - ); - }); - - it('js tokens for blue600 matches figma tokens blue600', () => { - expect(brandColor.blue600).toStrictEqual( - designTokens.global.brandColors.blue.blue600.value.toLowerCase(), - ); - }); - - it('js tokens for blue700 matches figma tokens blue700', () => { - expect(brandColor.blue700).toStrictEqual( - designTokens.global.brandColors.blue.blue700.value.toLowerCase(), - ); - }); - - it('js tokens for blue800 matches figma tokens blue800', () => { - expect(brandColor.blue800).toStrictEqual( - designTokens.global.brandColors.blue.blue800.value.toLowerCase(), - ); - }); - - it('js tokens for blue900 matches figma tokens blue900', () => { - expect(brandColor.blue900).toStrictEqual( - designTokens.global.brandColors.blue.blue900.value.toLowerCase(), - ); - }); - }); - - describe('Orange', () => { - it('js tokens for orange000 matches figma tokens orange000', () => { - expect(brandColor.orange000).toStrictEqual( - designTokens.global.brandColors.orange.orange000.value.toLowerCase(), - ); - }); - - it('js tokens for orange100 matches figma tokens orange100', () => { - expect(brandColor.orange100).toStrictEqual( - designTokens.global.brandColors.orange.orange100.value.toLowerCase(), - ); - }); - - it('js tokens for orange200 matches figma tokens orange200', () => { - expect(brandColor.orange200).toStrictEqual( - designTokens.global.brandColors.orange.orange200.value.toLowerCase(), - ); - }); - - it('js tokens for orange300 matches figma tokens orange300', () => { - expect(brandColor.orange300).toStrictEqual( - designTokens.global.brandColors.orange.orange300.value.toLowerCase(), - ); - }); - - it('js tokens for orange400 matches figma tokens orange400', () => { - expect(brandColor.orange400).toStrictEqual( - designTokens.global.brandColors.orange.orange400.value.toLowerCase(), - ); - }); - - it('js tokens for orange500 matches figma tokens orange500', () => { - expect(brandColor.orange500).toStrictEqual( - designTokens.global.brandColors.orange.orange500.value.toLowerCase(), - ); - }); - - it('js tokens for orange600 matches figma tokens orange600', () => { - expect(brandColor.orange600).toStrictEqual( - designTokens.global.brandColors.orange.orange600.value.toLowerCase(), - ); - }); - - it('js tokens for orange700 matches figma tokens orange700', () => { - expect(brandColor.orange700).toStrictEqual( - designTokens.global.brandColors.orange.orange700.value.toLowerCase(), - ); - }); - - it('js tokens for orange800 matches figma tokens orange800', () => { - expect(brandColor.orange800).toStrictEqual( - designTokens.global.brandColors.orange.orange800.value.toLowerCase(), - ); - }); - - it('js tokens for orange900 matches figma tokens orange900', () => { - expect(brandColor.orange900).toStrictEqual( - designTokens.global.brandColors.orange.orange900.value.toLowerCase(), - ); - }); - }); - - describe('Green', () => { - it('js tokens for green000 matches figma tokens green000', () => { - expect(brandColor.green000).toStrictEqual( - designTokens.global.brandColors.green.green000.value.toLowerCase(), - ); - }); - - it('js tokens for green100 matches figma tokens green100', () => { - expect(brandColor.green100).toStrictEqual( - designTokens.global.brandColors.green.green100.value.toLowerCase(), - ); - }); - - it('js tokens for green200 matches figma tokens green200', () => { - expect(brandColor.green200).toStrictEqual( - designTokens.global.brandColors.green.green200.value.toLowerCase(), - ); - }); - - it('js tokens for green300 matches figma tokens green300', () => { - expect(brandColor.green300).toStrictEqual( - designTokens.global.brandColors.green.green300.value.toLowerCase(), - ); - }); - - it('js tokens for green400 matches figma tokens green400', () => { - expect(brandColor.green400).toStrictEqual( - designTokens.global.brandColors.green.green400.value.toLowerCase(), - ); - }); - - it('js tokens for green500 matches figma tokens green500', () => { - expect(brandColor.green500).toStrictEqual( - designTokens.global.brandColors.green.green500.value.toLowerCase(), - ); - }); - - it('js tokens for green600 matches figma tokens green600', () => { - expect(brandColor.green600).toStrictEqual( - designTokens.global.brandColors.green.green600.value.toLowerCase(), - ); - }); - - it('js tokens for green700 matches figma tokens green700', () => { - expect(brandColor.green700).toStrictEqual( - designTokens.global.brandColors.green.green700.value.toLowerCase(), - ); - }); - - it('js tokens for green800 matches figma tokens green800', () => { - expect(brandColor.green800).toStrictEqual( - designTokens.global.brandColors.green.green800.value.toLowerCase(), - ); - }); - - it('js tokens for green900 matches figma tokens green900', () => { - expect(brandColor.green900).toStrictEqual( - designTokens.global.brandColors.green.green900.value.toLowerCase(), - ); - }); - }); - - describe('Red', () => { - it('js tokens for red000 matches figma tokens red000', () => { - expect(brandColor.red000).toStrictEqual( - designTokens.global.brandColors.red.red000.value.toLowerCase(), - ); - }); - - it('js tokens for red100 matches figma tokens red100', () => { - expect(brandColor.red100).toStrictEqual( - designTokens.global.brandColors.red.red100.value.toLowerCase(), - ); - }); - - it('js tokens for red200 matches figma tokens red200', () => { - expect(brandColor.red200).toStrictEqual( - designTokens.global.brandColors.red.red200.value.toLowerCase(), - ); - }); - - it('js tokens for red300 matches figma tokens red300', () => { - expect(brandColor.red300).toStrictEqual( - designTokens.global.brandColors.red.red300.value.toLowerCase(), - ); - }); - - it('js tokens for red400 matches figma tokens red400', () => { - expect(brandColor.red400).toStrictEqual( - designTokens.global.brandColors.red.red400.value.toLowerCase(), - ); - }); - - it('js tokens for red500 matches figma tokens red500', () => { - expect(brandColor.red500).toStrictEqual( - designTokens.global.brandColors.red.red500.value.toLowerCase(), - ); - }); - - it('js tokens for red600 matches figma tokens red600', () => { - expect(brandColor.red600).toStrictEqual( - designTokens.global.brandColors.red.red600.value.toLowerCase(), - ); - }); - - it('js tokens for red700 matches figma tokens red700', () => { - expect(brandColor.red700).toStrictEqual( - designTokens.global.brandColors.red.red700.value.toLowerCase(), - ); - }); - - it('js tokens for red800 matches figma tokens red800', () => { - expect(brandColor.red800).toStrictEqual( - designTokens.global.brandColors.red.red800.value.toLowerCase(), - ); - }); - - it('js tokens for red900 matches figma tokens red900', () => { - expect(brandColor.red900).toStrictEqual( - designTokens.global.brandColors.red.red900.value.toLowerCase(), - ); - }); - }); - - describe('Purple', () => { - it('js tokens for purple500 matches figma tokens purple500', () => { - expect(brandColor.purple500).toStrictEqual( - designTokens.global.brandColors.purple.purple500.value.toLowerCase(), - ); - }); - }); - - describe('Violet', () => { - it('js tokens for violet300 matches figma tokens violet300', () => { - expect(brandColor.violet300).toStrictEqual( - designTokens.global.brandColors.violet.violet300.value.toLowerCase(), - ); - }); - }); - - describe('Yellow', () => { - it('js tokens for yellow000 matches figma tokens yellow000', () => { - expect(brandColor.yellow000).toStrictEqual( - designTokens.global.brandColors.yellow.yellow000.value.toLowerCase(), - ); - }); - - it('js tokens for yellow100 matches figma tokens yellow100', () => { - expect(brandColor.yellow100).toStrictEqual( - designTokens.global.brandColors.yellow.yellow100.value.toLowerCase(), - ); - }); - - it('js tokens for yellow200 matches figma tokens yellow200', () => { - expect(brandColor.yellow200).toStrictEqual( - designTokens.global.brandColors.yellow.yellow200.value.toLowerCase(), - ); - }); - - it('js tokens for yellow300 matches figma tokens yellow300', () => { - expect(brandColor.yellow300).toStrictEqual( - designTokens.global.brandColors.yellow.yellow300.value.toLowerCase(), - ); - }); - - it('js tokens for yellow400 matches figma tokens yellow400', () => { - expect(brandColor.yellow400).toStrictEqual( - designTokens.global.brandColors.yellow.yellow400.value.toLowerCase(), - ); - }); - - it('js tokens for yellow500 matches figma tokens yellow500', () => { - expect(brandColor.yellow500).toStrictEqual( - designTokens.global.brandColors.yellow.yellow500.value.toLowerCase(), - ); - }); - - it('js tokens for yellow600 matches figma tokens yellow600', () => { - expect(brandColor.yellow600).toStrictEqual( - designTokens.global.brandColors.yellow.yellow600.value.toLowerCase(), - ); + Object.entries(brandColor).forEach(([key, value]) => { + const colorFamily = key.replace(/\d+.*$/u, ''); // Extracts 'grey' from 'grey000' + const shadeMatch = key.match(/\d+/gu); // Extracts ['000'] from 'grey000' + // if no numeric key is found, skip the test + if (!shadeMatch?.[0]) { + describe(`${colorFamily.toUpperCase()} `, () => { + it(`js tokens for ${key} matches figma brandColor ${colorFamily}`, () => { + const tokenValue = designTokens[colorFamily]?.value ?? ''; + expect(value.toLowerCase()).toStrictEqual(tokenValue.toLowerCase()); + }); + }); + return; + } + const shadeKey = shadeMatch[0]; // Ensures there's a valid shade key + + describe(`${colorFamily.toUpperCase()} ${shadeKey}`, () => { + it(`js tokens for ${key} matches figma brandColor ${colorFamily}${shadeKey}`, () => { + const tokenValue = designTokens[colorFamily][shadeKey]?.value ?? ''; + expect(value.toLowerCase()).toStrictEqual(tokenValue.toLowerCase()); + }); }); }); }); diff --git a/src/js/brandColor/brandColor.ts b/src/js/brandColor/brandColor.ts index 5761b3ec..e127111c 100644 --- a/src/js/brandColor/brandColor.ts +++ b/src/js/brandColor/brandColor.ts @@ -1,78 +1,188 @@ import type { BrandColor } from './brandColor.types'; export const brandColor: BrandColor = { - // White - white000: '#ffffff', - white010: '#fcfcfc', - // Black - black000: '#000000', // Grey - grey030: '#fafbfc', - grey040: '#f2f4f6', grey100: '#d6d9dc', + // Grey grey200: '#bbc0c5', + // Grey grey300: '#9fa6ae', + // Grey grey400: '#848c96', + // Grey grey500: '#6a737d', + // Grey grey600: '#535a61', + // Grey grey700: '#3b4046', - grey750: '#2e3339', + // Grey grey800: '#24272a', + // Grey grey900: '#141618', + // Grey + grey1000: '#000000', + // Grey + grey050: '#f2f4f6', + // Grey + grey000: '#ffffff', + // Grey + grey025: '#fafbfc', // Blue - blue000: '#eaf6ff', blue100: '#a7d9fe', + // Blue blue200: '#75c4fd', + // Blue blue300: '#43aefc', + // Blue blue400: '#1098fc', + // Blue blue500: '#0376c9', + // Blue blue600: '#0260a4', + // Blue blue700: '#024272', + // Blue blue800: '#01253f', + // Blue blue900: '#00080d', - // Orange - orange000: '#fef5ef', - orange100: '#fde2cf', - orange200: '#fbc49d', - orange300: '#faa66c', - orange400: '#f8883b', - orange500: '#f66a0a', - orange600: '#bf5208', - orange700: '#954005', - orange800: '#632b04', - orange900: '#321602', + // Blue + blue050: '#eaf6ff', + // Blue + blue025: '#eaf6ff', + // Green + green100: '#afecbd', + // Green + green200: '#5dd879', + // Green + green300: '#28a745', + // Green + green400: '#28a745', + // Green + green500: '#1c8234', + // Green + green600: '#145523', // Green - green000: '#f3fcf5', - green100: '#d6ffdf', - green200: '#afecbd', - green300: '#86e29b', - green400: '#5dd879', - green500: '#28a745', - green600: '#1c8234', green700: '#145523', + // Green green800: '#0a2c12', + // Green green900: '#041007', + // Green + green050: '#d6ffdf', + // Green + green025: '#f3fcf5', // Red - red000: '#fcf2f3', red100: '#f7d5d8', + // Red red200: '#f1b9be', + // Red red300: '#e88f97', + // Red red400: '#e06470', + // Red red500: '#d73847', - red600: '#b92534', - red700: '#8e1d28', - red800: '#64141c', + // Red + red600: '#8e1d28', + // Red + red700: '#64141c', + // Red + red800: '#3a0c10', + // Red red900: '#3a0c10', + // Red + red050: '#fcf2f3', + // Red + red025: '#fcf2f3', + // Yellow + yellow100: '#ffdf70', + // Yellow + yellow200: '#ffc70a', + // Yellow + yellow300: '#f8883b', + // Yellow + yellow400: '#f66a0a', + // Yellow + yellow500: '#bf5208', + // Yellow + yellow600: '#954005', + // Yellow + yellow700: '#632b04', + // Yellow + yellow800: '#321602', + // Yellow + yellow900: '#321602', + // Yellow + yellow050: '#fff2c5', + // Yellow + yellow025: '#fefcde', + // Orange + orange100: '#fbc49d', + // Orange + orange200: '#faa66c', + // Orange + orange300: '#f8883b', + // Orange + orange400: '#f66a0a', + // Orange + orange500: '#bf5208', + // Orange + orange600: '#954005', + // Orange + orange700: '#632b04', + // Orange + orange800: '#321602', + // Orange + orange900: '#321602', + // Orange + orange050: '#fde2cf', + // Orange + orange025: '#fef5ef', + // Purple + purple100: '#efd2ff', + // Purple + purple200: '#cfb5f0', + // Purple + purple300: '#d27dff', + // Purple + purple400: '#b864f5', // Purple purple500: '#8b45b6', - // Violet - violet300: '#cfb5f0', - // Yellow - yellow000: '#fffdf8', - yellow100: '#fefcde', - yellow200: '#fff2c5', - yellow300: '#ffeaa3', - yellow400: '#ffdf70', - yellow500: '#ffd33d', - yellow600: '#ffc70a', + // Purple + purple600: '#6c2ab2', + // Purple + purple700: '#4c1178', + // Purple + purple800: '#32054d', + // Purple + purple900: '#280a00', + // Purple + purple050: '#fbf2ff', + // Purple + purple025: '#fcf6ff', + // Lime + lime100: '#b8ef4a', + // Lime + lime200: '#95ca45', + // Lime + lime300: '#7ab040', + // Lime + lime400: '#64993d', + // Lime + lime500: '#457a39', + // Lime + lime600: '#275b35', + // Lime + lime700: '#093a31', + // Lime + lime800: '#022321', + // Lime + lime900: '#011515', + // Lime + lime025: '#effed9', + // Lime + lime050: '#e3febd', + // White + white: '#ffffff', + // Black + black: '#000000', }; diff --git a/src/js/brandColor/brandColor.types.ts b/src/js/brandColor/brandColor.types.ts index 1f323420..bc89df05 100644 --- a/src/js/brandColor/brandColor.types.ts +++ b/src/js/brandColor/brandColor.types.ts @@ -1,14 +1,4 @@ export type BrandColor = { - /** white/white000: #ffffff */ - white000: string; - /** white/white010: #fcfcfc */ - white010: string; - /** black/black000: #000000 */ - black000: string; - /** grey/grey030: #fafbfc */ - grey030: string; - /** grey/grey040: #f2f4f6 */ - grey040: string; /** grey/grey100: #d6d9dc */ grey100: string; /** grey/grey200: #bbc0c5 */ @@ -23,14 +13,18 @@ export type BrandColor = { grey600: string; /** grey/grey700: #3b4046 */ grey700: string; - /** grey/grey750: #2e3339 */ - grey750: string; /** grey/grey800: #24272a */ grey800: string; /** grey/grey900: #141618 */ grey900: string; - /** blue/blue000: #eaf6ff */ - blue000: string; + /** grey/grey1000: #000000 */ + grey1000: string; + /** grey/grey050: #f2f4f6 */ + grey050: string; + /** grey/grey000: #ffffff */ + grey000: string; + /** grey/grey025: #fafbfc */ + grey025: string; /** blue/blue100: #a7d9fe */ blue100: string; /** blue/blue200: #75c4fd */ @@ -49,39 +43,21 @@ export type BrandColor = { blue800: string; /** blue/blue900: #00080d */ blue900: string; - /** orange/orange000: #fef5ef */ - orange000: string; - /** orange/orange100: #fde2cf */ - orange100: string; - /** orange/orange200: #fbc49d */ - orange200: string; - /** orange/orange300: #faa66c */ - orange300: string; - /** orange/orange400: #f8883b */ - orange400: string; - /** orange/orange500: #f66a0a */ - orange500: string; - /** orange/orange600: #c65507 */ - orange600: string; - /** orange/orange700: #954005 */ - orange700: string; - /** orange/orange800: #632b04 */ - orange800: string; - /** orange/orange900: #321602 */ - orange900: string; - /** green/green000: #f3fcf5 */ - green000: string; - /** green/green100: #d6ffdf */ + /** blue/blue050: #eaf6ff */ + blue050: string; + /** blue/blue025: #eaf6ff */ + blue025: string; + /** green/green100: #afecbd */ green100: string; - /** green/green200: #afecbd */ + /** green/green200: #5dd879 */ green200: string; - /** green/green300: #86e29b */ + /** green/green300: #28a745 */ green300: string; - /** green/green400: #5dd879 */ + /** green/green400: #28a745 */ green400: string; - /** green/green500: #28a745 */ + /** green/green500: #1c8234 */ green500: string; - /** green/green600: #1e7e34 */ + /** green/green600: #145523 */ green600: string; /** green/green700: #145523 */ green700: string; @@ -89,8 +65,10 @@ export type BrandColor = { green800: string; /** green/green900: #041007 */ green900: string; - /** red/red000: #fcf2f3 */ - red000: string; + /** green/green050: #d6ffdf */ + green050: string; + /** green/green025: #f3fcf5 */ + green025: string; /** red/red100: #f7d5d8 */ red100: string; /** red/red200: #f1b9be */ @@ -101,30 +79,108 @@ export type BrandColor = { red400: string; /** red/red500: #d73847 */ red500: string; - /** red/red600: #b92534 */ + /** red/red600: #8e1d28 */ red600: string; - /** red/red700: #8e1d28 */ + /** red/red700: #64141c */ red700: string; - /** red/red800: #64141c */ + /** red/red800: #3a0c10 */ red800: string; /** red/red900: #3a0c10 */ red900: string; - /** purple/purple500: #8b45b6 */ - purple500: string; - /** violet/violet300: #cfb5f0 */ - violet300: string; - /** yellow/yellow000: #fffdf8 */ - yellow000: string; - /** yellow/yellow100: #fefcde */ + /** red/red050: #fcf2f3 */ + red050: string; + /** red/red025: #fcf2f3 */ + red025: string; + /** yellow/yellow100: #ffdf70 */ yellow100: string; - /** yellow/yellow200: #fff2c5 */ + /** yellow/yellow200: #ffc70a */ yellow200: string; - /** yellow/yellow300: #ffeaa3 */ + /** yellow/yellow300: #f8883b */ yellow300: string; - /** yellow/yellow400: #ffdf70 */ + /** yellow/yellow400: #f66a0a */ yellow400: string; - /** yellow/yellow500: #ffd33d */ + /** yellow/yellow500: #bf5208 */ yellow500: string; - /** yellow/yellow600: #ffc70a */ + /** yellow/yellow600: #954005 */ yellow600: string; + /** yellow/yellow700: #632b04 */ + yellow700: string; + /** yellow/yellow800: #321602 */ + yellow800: string; + /** yellow/yellow900: #321602 */ + yellow900: string; + /** yellow/yellow050: #fff2c5 */ + yellow050: string; + /** yellow/yellow025: #fefcde */ + yellow025: string; + /** orange/orange100: #fbc49d */ + orange100: string; + /** orange/orange200: #faa66c */ + orange200: string; + /** orange/orange300: #f8883b */ + orange300: string; + /** orange/orange400: #f66a0a */ + orange400: string; + /** orange/orange500: #bf5208 */ + orange500: string; + /** orange/orange600: #954005 */ + orange600: string; + /** orange/orange700: #632b04 */ + orange700: string; + /** orange/orange800: #321602 */ + orange800: string; + /** orange/orange900: #321602 */ + orange900: string; + /** orange/orange050: #fde2cf */ + orange050: string; + /** orange/orange025: #fef5ef */ + orange025: string; + /** purple/purple100: #efd2ff */ + purple100: string; + /** purple/purple200: #cfb5f0 */ + purple200: string; + /** purple/purple300: #d27dff */ + purple300: string; + /** purple/purple400: #b864f5 */ + purple400: string; + /** purple/purple500: #8b45b6 */ + purple500: string; + /** purple/purple600: #6c2ab2 */ + purple600: string; + /** purple/purple700: #4c1178 */ + purple700: string; + /** purple/purple800: #32054d */ + purple800: string; + /** purple/purple900: #280a00 */ + purple900: string; + /** purple/purple050: #fbf2ff */ + purple050: string; + /** purple/purple025: #fcf6ff */ + purple025: string; + /** lime/lime100: #b8ef4a */ + lime100: string; + /** lime/lime200: #95ca45 */ + lime200: string; + /** lime/lime300: #7ab040 */ + lime300: string; + /** lime/lime400: #64993d */ + lime400: string; + /** lime/lime500: #457a39 */ + lime500: string; + /** lime/lime600: #275b35 */ + lime600: string; + /** lime/lime700: #093a31 */ + lime700: string; + /** lime/lime800: #022321 */ + lime800: string; + /** lime/lime900: #011515 */ + lime900: string; + /** lime/lime025: #effed9 */ + lime025: string; + /** lime/lime050: #e3febd */ + lime050: string; + /** white: #ffffff */ + white: string; + /** black: #000000 */ + black: string; }; diff --git a/src/js/themes/darkTheme/colors.test.ts b/src/js/themes/darkTheme/colors.test.ts index ffb1724c..0b590e9f 100644 --- a/src/js/themes/darkTheme/colors.test.ts +++ b/src/js/themes/darkTheme/colors.test.ts @@ -1,390 +1,62 @@ -/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ -import { colors as importableColors } from './colors'; - -const designTokens = require('../../../figma/tokens.json'); - -describe('Dark Theme Colors', () => { - it('js tokens for background.default matches figma tokens background.default', () => { - expect(importableColors.background.default).toStrictEqual( - designTokens.dark.colors.background.default.value, - ); - }); - - it('js tokens for background.defaultHover matches figma tokens background.defaultHover', () => { - expect(importableColors.background.defaultHover).toStrictEqual( - designTokens.dark.colors.background['default-hover'].value, - ); - }); - - it('js tokens for background.defaultPressed matches figma tokens background.defaultPressed', () => { - expect(importableColors.background.defaultPressed).toStrictEqual( - designTokens.dark.colors.background['default-pressed'].value, - ); - }); - - it('js tokens for background.alternative matches figma tokens background.alternative', () => { - expect(importableColors.background.alternative).toStrictEqual( - designTokens.dark.colors.background.alternative.value, - ); - }); - - it('js tokens for background.alternativeHover matches figma tokens background.alternativeHover', () => { - expect(importableColors.background.alternativeHover).toStrictEqual( - designTokens.dark.colors.background['alternative-hover'].value, - ); - }); - - it('js tokens for background.alternativePressed matches figma tokens background.alternativePressed', () => { - expect(importableColors.background.alternativePressed).toStrictEqual( - designTokens.dark.colors.background['alternative-pressed'].value, - ); - }); - - it('js tokens for background.hover matches figma tokens background.hover', () => { - expect(importableColors.background.hover).toStrictEqual( - designTokens.dark.colors.background.hover.value, - ); - }); - - it('js tokens for background.pressed matches figma tokens background.pressed', () => { - expect(importableColors.background.pressed).toStrictEqual( - designTokens.dark.colors.background.pressed.value, - ); - }); - - it('js tokens for text.default matches figma tokens text.default', () => { - expect(importableColors.text.default).toStrictEqual( - designTokens.dark.colors.text.default.value, - ); - }); - - it('js tokens for text.alternative matches figma tokens text.alternative', () => { - expect(importableColors.text.alternative).toStrictEqual( - designTokens.dark.colors.text.alternative.value, - ); - }); - - it('js tokens for text.muted matches figma tokens text.muted', () => { - expect(importableColors.text.muted).toStrictEqual( - designTokens.dark.colors.text.muted.value, - ); - }); - - it('js tokens for icon.default matches figma tokens icon.default', () => { - expect(importableColors.icon.default).toStrictEqual( - designTokens.dark.colors.icon.default.value, - ); - }); - - it('js tokens for icon.alternative matches figma tokens icon.alternative', () => { - expect(importableColors.icon.alternative).toStrictEqual( - designTokens.dark.colors.icon.alternative.value, - ); - }); - - it('js tokens for icon.muted matches figma tokens icon.muted', () => { - expect(importableColors.icon.muted).toStrictEqual( - designTokens.dark.colors.icon.muted.value, - ); - }); - - it('js tokens for border.default matches figma tokens border.default', () => { - expect(importableColors.border.default).toStrictEqual( - designTokens.dark.colors.border.default.value, - ); - }); - - it('js tokens for border.muted matches figma tokens border.muted', () => { - expect(importableColors.border.muted).toStrictEqual( - designTokens.dark.colors.border.muted.value, - ); - }); - - it('js tokens for overlay.default matches figma tokens overlay.default', () => { - expect(importableColors.overlay.default).toStrictEqual( - designTokens.dark.colors.overlay.default.value, - ); - }); - - it('js tokens for overlay.alternative matches figma tokens overlay.alternative', () => { - expect(importableColors.overlay.alternative).toStrictEqual( - designTokens.dark.colors.overlay.alternative.value, - ); - }); - - it('js tokens for overlay.inverse matches figma tokens overlay.inverse', () => { - expect(importableColors.overlay.inverse).toStrictEqual( - designTokens.dark.colors.overlay.inverse.value, - ); - }); - - it('js tokens for shadow.default matches figma tokens dark.shadows.xs.value.color', () => { - expect(importableColors.shadow.default).toStrictEqual( - designTokens.dark.shadows.xs.value.color, - ); - - expect(importableColors.shadow.default).toStrictEqual( - designTokens.dark.shadows.sm.value.color, - ); - - expect(importableColors.shadow.default).toStrictEqual( - designTokens.dark.shadows.md.value.color, - ); - - expect(importableColors.shadow.default).toStrictEqual( - designTokens.dark.shadows.lg.value.color, - ); - }); - - it('js tokens for primary.default matches figma tokens primary.default', () => { - expect(importableColors.primary.default).toStrictEqual( - designTokens.dark.colors.primary.default.value, - ); - }); - - it('js tokens for primary.default-hover matches figma tokens primary.default-hover in dark mode', () => { - expect(importableColors.primary.defaultHover).toStrictEqual( - designTokens.dark.colors.primary['default-hover'].value, - ); - }); - - it('js tokens for primary.default-pressed matches figma tokens primary.default-pressed in dark mode', () => { - expect(importableColors.primary.defaultPressed).toStrictEqual( - designTokens.dark.colors.primary['default-pressed'].value, - ); - }); - - it('js tokens for primary.alternative matches figma tokens primary.alternative', () => { - expect(importableColors.primary.alternative).toStrictEqual( - designTokens.dark.colors.primary.alternative.value, - ); - }); - - it('js tokens for primary.muted matches figma tokens primary.muted', () => { - expect(importableColors.primary.muted).toStrictEqual( - designTokens.dark.colors.primary.muted.value, - ); - }); - - it('js tokens for primary.inverse matches figma tokens primary.inverse', () => { - expect(importableColors.primary.inverse).toStrictEqual( - designTokens.dark.colors.primary.inverse.value, - ); - }); - - it('js tokens for primary.shadow matches figma tokens shadows.primary', () => { - expect(importableColors.primary.shadow).toStrictEqual( - designTokens.dark.shadows.primary.value.color, - ); - }); - - it('js tokens for secondary.default matches figma tokens secondary.default', () => { - expect(importableColors.secondary.default).toStrictEqual( - designTokens.dark.colors.secondary.default.value, - ); - }); - - it('js tokens for secondary.alternative matches figma tokens secondary.alternative', () => { - expect(importableColors.secondary.alternative).toStrictEqual( - designTokens.dark.colors.secondary.alternative.value, - ); - }); - - it('js tokens for secondary.muted matches figma tokens secondary.muted', () => { - expect(importableColors.secondary.muted).toStrictEqual( - designTokens.dark.colors.secondary.muted.value, - ); - }); - - it('js tokens for secondary.inverse matches figma tokens secondary.inverse', () => { - expect(importableColors.secondary.inverse).toStrictEqual( - designTokens.dark.colors.secondary.inverse.value, - ); - }); - - it('js tokens for error.default matches figma tokens error.default', () => { - expect(importableColors.error.default).toStrictEqual( - designTokens.dark.colors.error.default.value, - ); - }); - - it('js tokens for error.default-hover matches figma tokens error.default-hover in dark mode', () => { - expect(importableColors.error.defaultHover).toStrictEqual( - designTokens.dark.colors.error['default-hover'].value, - ); - }); - - it('js tokens for error.default-pressed matches figma tokens error.default-pressed in dark mode', () => { - expect(importableColors.error.defaultPressed).toStrictEqual( - designTokens.dark.colors.error['default-pressed'].value, - ); - }); - - it('js tokens for error.alternative matches figma tokens error.alternative', () => { - expect(importableColors.error.alternative).toStrictEqual( - designTokens.dark.colors.error.alternative.value, - ); - }); - - it('js tokens for error.muted matches figma tokens error.muted', () => { - expect(importableColors.error.muted).toStrictEqual( - designTokens.dark.colors.error.muted.value, - ); - }); - - it('js tokens for error.inverse matches figma tokens error.inverse', () => { - expect(importableColors.error.inverse).toStrictEqual( - designTokens.dark.colors.error.inverse.value, - ); - }); - - it('js tokens for error.shadow matches figma tokens shadows.error', () => { - expect(importableColors.error.shadow).toStrictEqual( - designTokens.dark.shadows.error.value.color, - ); - }); - - it('js tokens for warning.default matches figma tokens warning.default', () => { - expect(importableColors.warning.default).toStrictEqual( - designTokens.dark.colors.warning.default.value, - ); - }); - - it('js tokens for warning.default-hover matches figma tokens warning.default-hover in dark mode', () => { - expect(importableColors.warning.defaultHover).toStrictEqual( - designTokens.dark.colors.warning['default-hover'].value, - ); - }); - - it('js tokens for warning.default-pressed matches figma tokens warning.default-pressed in dark mode', () => { - expect(importableColors.warning.defaultPressed).toStrictEqual( - designTokens.dark.colors.warning['default-pressed'].value, - ); - }); - - it('js tokens for warning.alternative matches figma tokens warning.alternative', () => { - expect(importableColors.warning.alternative).toStrictEqual( - designTokens.dark.colors.warning.alternative.value, - ); - }); - - it('js tokens for warning.muted matches figma tokens warning.muted', () => { - expect(importableColors.warning.muted).toStrictEqual( - designTokens.dark.colors.warning.muted.value, - ); - }); - - it('js tokens for warning.inverse matches figma tokens warning.inverse', () => { - expect(importableColors.warning.inverse).toStrictEqual( - designTokens.dark.colors.warning.inverse.value, - ); - }); - - it('js tokens for success.default matches figma tokens success.default', () => { - expect(importableColors.success.default).toStrictEqual( - designTokens.dark.colors.success.default.value, - ); - }); - - it('js tokens for success.default-hover matches figma tokens success.default-hover in dark mode', () => { - expect(importableColors.success.defaultHover).toStrictEqual( - designTokens.dark.colors.success['default-hover'].value, - ); - }); - - it('js tokens for success.default-pressed matches figma tokens success.default-pressed in dark mode', () => { - expect(importableColors.success.defaultPressed).toStrictEqual( - designTokens.dark.colors.success['default-pressed'].value, - ); - }); - - it('js tokens for success.alternative matches figma tokens success.alternative', () => { - expect(importableColors.success.alternative).toStrictEqual( - designTokens.dark.colors.success.alternative.value, - ); - }); - - it('js tokens for success.muted matches figma tokens success.muted', () => { - expect(importableColors.success.muted).toStrictEqual( - designTokens.dark.colors.success.muted.value, - ); - }); - - it('js tokens for success.inverse matches figma tokens success.inverse', () => { - expect(importableColors.success.inverse).toStrictEqual( - designTokens.dark.colors.success.inverse.value, - ); - }); - - it('js tokens for info.default matches figma tokens info.default', () => { - expect(importableColors.info.default).toStrictEqual( - designTokens.dark.colors.info.default.value, - ); - }); - - it('js tokens for info.alternative matches figma tokens info.alternative', () => { - expect(importableColors.info.alternative).toStrictEqual( - designTokens.dark.colors.info.alternative.value, - ); - }); - - it('js tokens for info.muted matches figma tokens info.muted', () => { - expect(importableColors.info.muted).toStrictEqual( - designTokens.dark.colors.info.muted.value, - ); - }); - - it('js tokens for info.inverse matches figma tokens info.inverse', () => { - expect(importableColors.info.inverse).toStrictEqual( - designTokens.dark.colors.info.inverse.value, - ); - }); - - it('js tokens for networks.goerli.default matches figma tokens networks.goerli.default', () => { - expect(importableColors.networks.goerli.default).toStrictEqual( - designTokens.dark.colors.networks.goerli.default.value, - ); - }); - - it('js tokens for networks.goerli.inverse matches figma tokens networks.goerli.inverse', () => { - expect(importableColors.networks.goerli.inverse).toStrictEqual( - designTokens.dark.colors.networks.goerli.inverse.value, - ); - }); - - it('js tokens for networks.localhost.default matches figma tokens networks.localhost.default', () => { - expect(importableColors.networks.localhost.default).toStrictEqual( - designTokens.dark.colors.networks.localhost.default.value, - ); - }); - - it('js tokens for networks.localhost.inverse matches figma tokens networks.localhost.inverse', () => { - expect(importableColors.networks.localhost.inverse).toStrictEqual( - designTokens.dark.colors.networks.localhost.inverse.value, - ); - }); - - it('js tokens for networks.sepolia.default matches figma tokens networks.sepolia.default', () => { - expect(importableColors.networks.sepolia.default).toStrictEqual( - designTokens.dark.colors.networks.sepolia.default.value, - ); - }); - - it('js tokens for networks.sepolia.inverse matches figma tokens networks.sepolia.inverse', () => { - expect(importableColors.networks.sepolia.inverse).toStrictEqual( - designTokens.dark.colors.networks.sepolia.inverse.value, - ); - }); - - it('js tokens for flask.default matches figma tokens flask.default', () => { - expect(importableColors.flask.default).toStrictEqual( - designTokens.dark.colors.flask.default.value, - ); - }); - - it('js tokens for flask.inverse matches figma tokens flask.inverse', () => { - expect(importableColors.flask.inverse).toStrictEqual( - designTokens.dark.colors.flask.inverse.value, - ); +import * as brandColors from '../../../figma/brandColors.json'; +import * as darkTheme from '../../../figma/darkTheme.json'; +import { colors as definedColors } from './colors'; + +type ColorDetails = { + value: string; + type: string; + parent: string; + description: string; +}; + +/** + * Recursively resolve color references in a theme object. + * @param theme - Object containing theme definitions. + * @param colors - Object containing color definitions. + * @param rootTheme - Root theme object. + */ +function resolveColorReferences( + theme: any, + colors: any, + rootTheme?: any, +): void { + Object.keys(theme).forEach((key) => { + if (typeof theme[key] === 'object' && theme[key] !== null) { + resolveColorReferences(theme[key], colors, rootTheme || theme); + } else if (typeof theme[key] === 'string' && theme[key].startsWith('{')) { + const match = theme[key].match(/\{(.+?)\}/u); + if (match) { + const [colorFamily, shade] = match[1].split('.'); + if (colors[colorFamily]?.[shade]) { + theme[key] = colors[colorFamily][shade].value; + } else if (rootTheme?.[colorFamily]?.[shade]?.value) { + theme[key] = rootTheme[colorFamily][shade].value; + } + } + } + }); +} + +describe('Theme Color Resolution', () => { + const clonedTheme = JSON.parse(JSON.stringify(darkTheme)) as { + [key: string]: { [key: string]: ColorDetails }; + }; + resolveColorReferences(clonedTheme, brandColors, clonedTheme); + + Object.entries(clonedTheme).forEach(([category, details]) => { + if (category !== 'default') { + // Skip 'default' category if it's not part of definedColors + Object.entries(details).forEach(([key, detail]) => { + const cleanKey = key + .replace(/\*/gu, '') + .replace(/-([a-z])/gu, (_, p1) => p1.toUpperCase()) + .replace(/\s*\(strong\)\s*/gu, ''); + it(`ensures ${category}.${cleanKey} matches defined color`, () => { + expect((definedColors as any)[category][cleanKey]).toStrictEqual( + detail.value, + ); + }); + }); + } }); }); diff --git a/src/js/themes/darkTheme/colors.ts b/src/js/themes/darkTheme/colors.ts index 09c9f1f1..ed8219f7 100644 --- a/src/js/themes/darkTheme/colors.ts +++ b/src/js/themes/darkTheme/colors.ts @@ -1,110 +1,78 @@ +import { brandColor } from '../../brandColor'; import type { ThemeColors } from '../types'; -/** - * Dark theme colors - */ - export const colors: ThemeColors = { background: { - default: '#24272A', - defaultHover: '#282B2E', - defaultPressed: '#36383B', - alternative: '#141618', - alternativeHover: '#191B1D', - alternativePressed: '#27292A', - hover: '#FFFFFF05', - pressed: '#FFFFFF14', + default: brandColor.grey800, // For default neutral backgrounds + alternative: brandColor.grey900, // For secondary neutral backgrounds. + defaultHover: '#313235', // For "hover" states that use background-default. + defaultPressed: '#3f4145', // For "pressed" states that use background-alternative. + alternativeHover: '#1f2123', // For "hover" states that use background-alternative. + alternativePressed: '#2e3033', // For "pressed" states that use background-alternative. + hover: '#ffffff0a', // For "hover" state that use no background fill. + pressed: '#ffffff14', // For "pressed" state that use no background fill. }, text: { - default: '#FFFFFF', - alternative: '#D6D9DC', - muted: '#9FA6AE', + default: brandColor.grey000, // For default neutral text. + alternative: brandColor.grey200, // For softer contrast neutral text + muted: brandColor.grey400, // For the softest contrast neutral text (not accessible) }, icon: { - default: '#FFFFFF', - alternative: '#BBC0C5', - muted: '#9FA6AE', + default: brandColor.grey000, // For default neutral icons + alternative: brandColor.grey200, // For softer neutral icons + muted: brandColor.grey400, // For the weakest contrast neutral icons (not accessible) }, border: { - default: '#848C96', - muted: '#3B4046', + default: brandColor.grey400, // For soft contrast neutral border + muted: '#848c9629', // For the weakest contrast neutral border }, overlay: { - default: '#00000099', - inverse: '#FCFCFC', - alternative: '#000000CC', - }, - shadow: { - default: '#00000066', + default: '#00000099', // For the default shade of screen + alternative: '#000000cc', // For a stronger shade of screen + inverse: brandColor.grey000, // For elements used on top of overlay/alternative. Used for text, icon or border }, primary: { - default: '#1098FC', - defaultHover: '#0092FA', - defaultPressed: '#54B6FC', - alternative: '#43AEFC', - muted: '#1098FC26', - inverse: '#141618', - disabled: '#1098FC80', - shadow: '#1098FC66', - }, - secondary: { - default: '#F8883B', - alternative: '#FAA66C', - muted: '#F8883B26', - inverse: '#FCFCFC', - disabled: '#F8883B80', + default: brandColor.blue300, // For interactive, active, and selected semantics. Used for text, background, icon or border + alternative: brandColor.blue200, // For the stronger contrast primary semantic elements. + muted: '#43aefc26', // For the weakest contrast primary semantic backgrounds. + inverse: brandColor.grey900, // For elements used on top of primary/default. Used for text, icon or border + defaultHover: '#26a2fc', // For the "hover" state of primary-default elements + defaultPressed: '#3baafd', // For the "pressed" state of primary-default elements }, error: { - default: '#FF5263', - defaultHover: '#FF4D58', - defaultPressed: '#F9868E', - alternative: '#E88F97', - muted: '#FF526326', - inverse: '#141618', - disabled: '#D7384780', - shadow: '#FF526366', + default: brandColor.red300, // For the critical alert semantic elements. Used for text, background, icon or border + alternative: brandColor.red200, // For the stronger contrast error semantic elements. + muted: '#e88f9726', // For the weakest contrast critical alert semantic backgrounds. + inverse: brandColor.grey900, // For elements used on top of error/default. Used for text, icon or border + defaultHover: '#e47782', // For the "hover" state of error-default elements. + defaultPressed: '#e78891', // For the "pressed" state of error-default elements. }, warning: { - default: '#FFD33D', - defaultHover: '#FFC60A', - defaultPressed: '#FFEAA3D1', - alternative: '#FFDF70', - muted: '#FFD33D26', - inverse: '#141618', - disabled: '#FFD33D80', + default: brandColor.yellow100, // For the caution alert semantic elements. Used for text, background, icon or border + muted: '#ffdf7026', // For the weakest contrast caution alert semantic backgrounds. + inverse: brandColor.grey900, // For elements used on top of warning/default. Used for text, icon or border + defaultHover: '#ffe485', // For the "hover" state of warning-default elements + defaultPressed: '#ffe899', // For the "pressed" state of warning-default elements }, success: { - default: '#28A745', - defaultHover: '#05B82F', - defaultPressed: '#6AEC88', - alternative: '#5DD879', - muted: '#28A74526', - inverse: '#141618', - disabled: '#28A74580', + default: brandColor.green300, // For the positive semantic elements. Used for text, background, icon or border + muted: '#28a74526', // For the weakest contrast positive semantic backgrounds. + inverse: brandColor.grey900, // For elements used on top of success/default. Used for text, icon or border + defaultHover: '#2cb94c', // For the "hover" state of success-default elements + defaultPressed: '#30ca53', // For the "pressed" state of success-default elements }, info: { - default: '#1098FC', - alternative: '#43AEFC', - muted: '#1098FC26', - inverse: '#141618', - disabled: '#0376C980', - }, - networks: { - goerli: { - default: '#1098FC', - inverse: '#FCFCFC', - }, - localhost: { - default: '#BBC0C5', - inverse: '#FCFCFC', - }, - sepolia: { - default: '#CFB5F0', - inverse: '#FCFCFC', - }, + default: brandColor.blue300, // For informational read-only elements. Used for text, background, icon or border + muted: '#43aefc26', // For the weakest contrast informational semantic backgrounds. + inverse: brandColor.grey900, // For elements used on top of info/default. Used for text, icon or border }, flask: { - default: '#8B45B6', - inverse: '#FCFCFC', + default: brandColor.purple300, // For Flask primary accent color. + inverse: brandColor.grey900, // For elements used on top of flask/default. Used for text, icon or border + }, + shadow: { + default: '#00000066', // For neutral drop shadow color. + primary: '#43aefc33', // For primary drop shadow color. + error: '#ff758466', // For critical/danger drop shadow color. }, }; diff --git a/src/js/themes/darkTheme/darkTheme.test.ts b/src/js/themes/darkTheme/darkTheme.test.ts index a064f55f..64c9a97b 100644 --- a/src/js/themes/darkTheme/darkTheme.test.ts +++ b/src/js/themes/darkTheme/darkTheme.test.ts @@ -1,13 +1,14 @@ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ import { darkTheme } from './darkTheme'; +const jsonDarkThemeTokens = require('../../../figma/darkTheme.json'); const designTokens = require('../../../figma/tokens.json'); describe('dark Theme', () => { - it('color tokens are exported from darkTheme by checking first color token', () => { - expect(darkTheme.colors.background.default).toStrictEqual( - designTokens.dark.colors.background.default.value, - ); + it('color tokens are exported from darkTheme by checking a random color token', () => { + expect( + darkTheme.colors.background.defaultHover.toLowerCase(), + ).toStrictEqual(jsonDarkThemeTokens.background['default-hover'].value); }); it('typography tokens are exported from darkTheme by checking first typography token', () => { @@ -18,7 +19,7 @@ describe('dark Theme', () => { it('shadow tokens are exported from darkTheme by checking first shadow size object', () => { expect(darkTheme.shadows.size.xs).toStrictEqual({ - shadowColor: designTokens.dark.shadows.xs.value.color, + shadowColor: jsonDarkThemeTokens.shadow.default.value, shadowOffset: { width: Number(designTokens.dark.shadows.xs.value.x), height: Number(designTokens.dark.shadows.xs.value.y), diff --git a/src/js/themes/darkTheme/shadows.test.ts b/src/js/themes/darkTheme/shadows.test.ts index a69b5c33..d1dc04a7 100644 --- a/src/js/themes/darkTheme/shadows.test.ts +++ b/src/js/themes/darkTheme/shadows.test.ts @@ -1,12 +1,13 @@ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ import { shadows } from './shadows'; +const jsonDarkThemeTokens = require('../../../figma/darkTheme.json'); const designTokens = require('../../../figma/tokens.json'); describe('Shadows', () => { it('js tokens shadows.size.xs matches figma tokens shadows.xs', () => { expect(shadows.size.xs.shadowColor).toStrictEqual( - designTokens.dark.shadows.xs.value.color, + jsonDarkThemeTokens.shadow.default.value, ); expect(shadows.size.xs.shadowOffset.width).toStrictEqual( @@ -26,7 +27,7 @@ describe('Shadows', () => { it('js tokens shadows.size.sm matches figma tokens shadows.sm', () => { expect(shadows.size.sm.shadowColor).toStrictEqual( - designTokens.dark.shadows.sm.value.color, + jsonDarkThemeTokens.shadow.default.value, ); expect(shadows.size.sm.shadowOffset.width).toStrictEqual( @@ -46,7 +47,7 @@ describe('Shadows', () => { it('js tokens shadows.size.md matches figma tokens shadows.md', () => { expect(shadows.size.md.shadowColor).toStrictEqual( - designTokens.dark.shadows.md.value.color, + jsonDarkThemeTokens.shadow.default.value, ); expect(shadows.size.md.shadowOffset.width).toStrictEqual( @@ -66,7 +67,7 @@ describe('Shadows', () => { it('js tokens shadows.size.lg matches figma tokens shadows.lg', () => { expect(shadows.size.lg.shadowColor).toStrictEqual( - designTokens.dark.shadows.lg.value.color, + jsonDarkThemeTokens.shadow.default.value, ); expect(shadows.size.lg.shadowOffset.width).toStrictEqual( diff --git a/src/js/themes/lightTheme/colors.test.ts b/src/js/themes/lightTheme/colors.test.ts index 91b13cf7..5c4e04f5 100644 --- a/src/js/themes/lightTheme/colors.test.ts +++ b/src/js/themes/lightTheme/colors.test.ts @@ -1,390 +1,62 @@ -/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ -import { colors as importableColors } from './colors'; - -const designTokens = require('../../../figma/tokens.json'); - -describe('Light Theme Colors', () => { - it('js tokens for background.default matches figma tokens background.default', () => { - expect(importableColors.background.default).toStrictEqual( - designTokens.light.colors.background.default.value, - ); - }); - - it('js tokens for background.defaultHover matches figma tokens background.defaultHover', () => { - expect(importableColors.background.defaultHover).toStrictEqual( - designTokens.light.colors.background['default-hover'].value, - ); - }); - - it('js tokens for background.defaultPressed matches figma tokens background.defaultPressed', () => { - expect(importableColors.background.defaultPressed).toStrictEqual( - designTokens.light.colors.background['default-pressed'].value, - ); - }); - - it('js tokens for background.alternative matches figma tokens background.alternative', () => { - expect(importableColors.background.alternative).toStrictEqual( - designTokens.light.colors.background.alternative.value, - ); - }); - - it('js tokens for background.alternativeHover matches figma tokens background.alternativeHover', () => { - expect(importableColors.background.alternativeHover).toStrictEqual( - designTokens.light.colors.background['alternative-hover'].value, - ); - }); - - it('js tokens for background.alternativePressed matches figma tokens background.alternativePressed', () => { - expect(importableColors.background.alternativePressed).toStrictEqual( - designTokens.light.colors.background['alternative-pressed'].value, - ); - }); - - it('js tokens for background.hover matches figma tokens background.hover', () => { - expect(importableColors.background.hover).toStrictEqual( - designTokens.light.colors.background.hover.value, - ); - }); - - it('js tokens for background.pressed matches figma tokens background.pressed', () => { - expect(importableColors.background.pressed).toStrictEqual( - designTokens.light.colors.background.pressed.value, - ); - }); - - it('js tokens for text.default matches figma tokens text.default', () => { - expect(importableColors.text.default).toStrictEqual( - designTokens.light.colors.text.default.value, - ); - }); - - it('js tokens for text.alternative matches figma tokens text.alternative', () => { - expect(importableColors.text.alternative).toStrictEqual( - designTokens.light.colors.text.alternative.value, - ); - }); - - it('js tokens for text.muted matches figma tokens text.muted', () => { - expect(importableColors.text.muted).toStrictEqual( - designTokens.light.colors.text.muted.value, - ); - }); - - it('js tokens for icon.default matches figma tokens icon.default', () => { - expect(importableColors.icon.default).toStrictEqual( - designTokens.light.colors.icon.default.value, - ); - }); - - it('js tokens for icon.alternative matches figma tokens icon.alternative', () => { - expect(importableColors.icon.alternative).toStrictEqual( - designTokens.light.colors.icon.alternative.value, - ); - }); - - it('js tokens for icon.muted matches figma tokens icon.muted', () => { - expect(importableColors.icon.muted).toStrictEqual( - designTokens.light.colors.icon.muted.value, - ); - }); - - it('js tokens for border.default matches figma tokens border.default', () => { - expect(importableColors.border.default).toStrictEqual( - designTokens.light.colors.border.default.value, - ); - }); - - it('js tokens for border.muted matches figma tokens border.muted', () => { - expect(importableColors.border.muted).toStrictEqual( - designTokens.light.colors.border.muted.value, - ); - }); - - it('js tokens for overlay.default matches figma tokens overlay.default', () => { - expect(importableColors.overlay.default).toStrictEqual( - designTokens.light.colors.overlay.default.value, - ); - }); - - it('js tokens for overlay.alternative matches figma tokens overlay.alternative', () => { - expect(importableColors.overlay.alternative).toStrictEqual( - designTokens.light.colors.overlay.alternative.value, - ); - }); - - it('js tokens for overlay.inverse matches figma tokens overlay.inverse', () => { - expect(importableColors.overlay.inverse).toStrictEqual( - designTokens.light.colors.overlay.inverse.value, - ); - }); - - it('js tokens for shadow.default matches figma tokens light.shadows.xs.value.color', () => { - expect(importableColors.shadow.default).toStrictEqual( - designTokens.light.shadows.xs.value.color, - ); - - expect(importableColors.shadow.default).toStrictEqual( - designTokens.light.shadows.sm.value.color, - ); - - expect(importableColors.shadow.default).toStrictEqual( - designTokens.light.shadows.md.value.color, - ); - - expect(importableColors.shadow.default).toStrictEqual( - designTokens.light.shadows.lg.value.color, - ); - }); - - it('js tokens for primary.default matches figma tokens primary.default', () => { - expect(importableColors.primary.default).toStrictEqual( - designTokens.light.colors.primary.default.value, - ); - }); - - it('js tokens for primary.default-hover matches figma tokens primary.default-hover', () => { - expect(importableColors.primary.defaultHover).toStrictEqual( - designTokens.light.colors.primary['default-hover'].value, - ); - }); - - it('js tokens for primary.default-pressed matches figma tokens primary.default-pressed', () => { - expect(importableColors.primary.defaultPressed).toStrictEqual( - designTokens.light.colors.primary['default-pressed'].value, - ); - }); - - it('js tokens for primary.alternative matches figma tokens primary.alternative', () => { - expect(importableColors.primary.alternative).toStrictEqual( - designTokens.light.colors.primary.alternative.value, - ); - }); - - it('js tokens for primary.muted matches figma tokens primary.muted', () => { - expect(importableColors.primary.muted).toStrictEqual( - designTokens.light.colors.primary.muted.value, - ); - }); - - it('js tokens for primary.inverse matches figma tokens primary.inverse', () => { - expect(importableColors.primary.inverse).toStrictEqual( - designTokens.light.colors.primary.inverse.value, - ); - }); - - it('js tokens for primary.shadow matches figma tokens shadows.primary', () => { - expect(importableColors.primary.shadow).toStrictEqual( - designTokens.light.shadows.primary.value.color, - ); - }); - - it('js tokens for secondary.default matches figma tokens secondary.default', () => { - expect(importableColors.secondary.default).toStrictEqual( - designTokens.light.colors.secondary.default.value, - ); - }); - - it('js tokens for secondary.alternative matches figma tokens secondary.alternative', () => { - expect(importableColors.secondary.alternative).toStrictEqual( - designTokens.light.colors.secondary.alternative.value, - ); - }); - - it('js tokens for secondary.muted matches figma tokens secondary.muted', () => { - expect(importableColors.secondary.muted).toStrictEqual( - designTokens.light.colors.secondary.muted.value, - ); - }); - - it('js tokens for secondary.inverse matches figma tokens secondary.inverse', () => { - expect(importableColors.secondary.inverse).toStrictEqual( - designTokens.light.colors.secondary.inverse.value, - ); - }); - - it('js tokens for error.default matches figma tokens error.default', () => { - expect(importableColors.error.default).toStrictEqual( - designTokens.light.colors.error.default.value, - ); - }); - - it('js tokens for error.default-hover matches figma tokens error.default-hover', () => { - expect(importableColors.error.defaultHover).toStrictEqual( - designTokens.light.colors.error['default-hover'].value, - ); - }); - - it('js tokens for error.default-pressed matches figma tokens error.default-pressed', () => { - expect(importableColors.error.defaultPressed).toStrictEqual( - designTokens.light.colors.error['default-pressed'].value, - ); - }); - - it('js tokens for error.alternative matches figma tokens error.alternative', () => { - expect(importableColors.error.alternative).toStrictEqual( - designTokens.light.colors.error.alternative.value, - ); - }); - - it('js tokens for error.muted matches figma tokens error.muted', () => { - expect(importableColors.error.muted).toStrictEqual( - designTokens.light.colors.error.muted.value, - ); - }); - - it('js tokens for error.inverse matches figma tokens error.inverse', () => { - expect(importableColors.error.inverse).toStrictEqual( - designTokens.light.colors.error.inverse.value, - ); - }); - - it('js tokens for error.shadow matches figma tokens shadows.error', () => { - expect(importableColors.error.shadow).toStrictEqual( - designTokens.light.shadows.error.value.color, - ); - }); - - it('js tokens for warning.default matches figma tokens warning.default', () => { - expect(importableColors.warning.default).toStrictEqual( - designTokens.light.colors.warning.default.value, - ); - }); - - it('js tokens for warning.default-hover matches figma tokens warning.default-hover', () => { - expect(importableColors.warning.defaultHover).toStrictEqual( - designTokens.light.colors.warning['default-hover'].value, - ); - }); - - it('js tokens for warning.default-pressed matches figma tokens warning.default-pressed', () => { - expect(importableColors.warning.defaultPressed).toStrictEqual( - designTokens.light.colors.warning['default-pressed'].value, - ); - }); - - it('js tokens for warning.alternative matches figma tokens warning.alternative', () => { - expect(importableColors.warning.alternative).toStrictEqual( - designTokens.light.colors.warning.alternative.value, - ); - }); - - it('js tokens for warning.muted matches figma tokens warning.muted', () => { - expect(importableColors.warning.muted).toStrictEqual( - designTokens.light.colors.warning.muted.value, - ); - }); - - it('js tokens for warning.inverse matches figma tokens warning.inverse', () => { - expect(importableColors.warning.inverse).toStrictEqual( - designTokens.light.colors.warning.inverse.value, - ); - }); - - it('js tokens for success.default matches figma tokens success.default', () => { - expect(importableColors.success.default).toStrictEqual( - designTokens.light.colors.success.default.value, - ); - }); - - it('js tokens for success.default-hover matches figma tokens success.default-hover', () => { - expect(importableColors.success.defaultHover).toStrictEqual( - designTokens.light.colors.success['default-hover'].value, - ); - }); - - it('js tokens for success.default-pressed matches figma tokens success.default-pressed', () => { - expect(importableColors.success.defaultPressed).toStrictEqual( - designTokens.light.colors.success['default-pressed'].value, - ); - }); - - it('js tokens for success.alternative matches figma tokens success.alternative', () => { - expect(importableColors.success.alternative).toStrictEqual( - designTokens.light.colors.success.alternative.value, - ); - }); - - it('js tokens for success.muted matches figma tokens success.muted', () => { - expect(importableColors.success.muted).toStrictEqual( - designTokens.light.colors.success.muted.value, - ); - }); - - it('js tokens for success.inverse matches figma tokens success.inverse', () => { - expect(importableColors.success.inverse).toStrictEqual( - designTokens.light.colors.success.inverse.value, - ); - }); - - it('js tokens for info.default matches figma tokens info.default', () => { - expect(importableColors.info.default).toStrictEqual( - designTokens.light.colors.info.default.value, - ); - }); - - it('js tokens for info.alternative matches figma tokens info.alternative', () => { - expect(importableColors.info.alternative).toStrictEqual( - designTokens.light.colors.info.alternative.value, - ); - }); - - it('js tokens for info.muted matches figma tokens info.muted', () => { - expect(importableColors.info.muted).toStrictEqual( - designTokens.light.colors.info.muted.value, - ); - }); - - it('js tokens for info.inverse matches figma tokens info.inverse', () => { - expect(importableColors.info.inverse).toStrictEqual( - designTokens.light.colors.info.inverse.value, - ); - }); - - it('js tokens for networks.goerli.default matches figma tokens networks.goerli.default', () => { - expect(importableColors.networks.goerli.default).toStrictEqual( - designTokens.light.colors.networks.goerli.default.value, - ); - }); - - it('js tokens for networks.goerli.inverse matches figma tokens networks.goerli.inverse', () => { - expect(importableColors.networks.goerli.inverse).toStrictEqual( - designTokens.light.colors.networks.goerli.inverse.value, - ); - }); - - it('js tokens for networks.localhost.default matches figma tokens networks.localhost.default', () => { - expect(importableColors.networks.localhost.default).toStrictEqual( - designTokens.light.colors.networks.localhost.default.value, - ); - }); - - it('js tokens for networks.localhost.inverse matches figma tokens networks.localhost.inverse', () => { - expect(importableColors.networks.localhost.inverse).toStrictEqual( - designTokens.light.colors.networks.localhost.inverse.value, - ); - }); - - it('js tokens for networks.sepolia.default matches figma tokens networks.sepolia.default', () => { - expect(importableColors.networks.sepolia.default).toStrictEqual( - designTokens.light.colors.networks.sepolia.default.value, - ); - }); - - it('js tokens for networks.sepolia.inverse matches figma tokens networks.sepolia.inverse', () => { - expect(importableColors.networks.sepolia.inverse).toStrictEqual( - designTokens.light.colors.networks.sepolia.inverse.value, - ); - }); - - it('js tokens for flask.default matches figma tokens flask.default', () => { - expect(importableColors.flask.default).toStrictEqual( - designTokens.light.colors.flask.default.value, - ); - }); - - it('js tokens for flask.inverse matches figma tokens flask.inverse', () => { - expect(importableColors.flask.inverse).toStrictEqual( - designTokens.light.colors.flask.inverse.value, - ); +import * as brandColors from '../../../figma/brandColors.json'; +import * as lightTheme from '../../../figma/lightTheme.json'; +import { colors as definedColors } from './colors'; + +type ColorDetails = { + value: string; + type: string; + parent: string; + description: string; +}; + +/** + * Recursively resolve color references in a theme object. + * @param theme - Object containing theme definitions. + * @param colors - Object containing color definitions. + * @param rootTheme - Root theme object. + */ +function resolveColorReferences( + theme: any, + colors: any, + rootTheme?: any, +): void { + Object.keys(theme).forEach((key) => { + if (typeof theme[key] === 'object' && theme[key] !== null) { + resolveColorReferences(theme[key], colors, rootTheme || theme); + } else if (typeof theme[key] === 'string' && theme[key].startsWith('{')) { + const match = theme[key].match(/\{(.+?)\}/u); + if (match) { + const [colorFamily, shade] = match[1].split('.'); + if (colors[colorFamily]?.[shade]) { + theme[key] = colors[colorFamily][shade].value; + } else if (rootTheme?.[colorFamily]?.[shade]?.value) { + theme[key] = rootTheme[colorFamily][shade].value; + } + } + } + }); +} + +describe('Theme Color Resolution', () => { + const clonedTheme = JSON.parse(JSON.stringify(lightTheme)) as { + [key: string]: { [key: string]: ColorDetails }; + }; + resolveColorReferences(clonedTheme, brandColors, clonedTheme); + + Object.entries(clonedTheme).forEach(([category, details]) => { + if (category !== 'default') { + // Skip 'default' category if it's not part of definedColors + Object.entries(details).forEach(([key, detail]) => { + const cleanKey = key + .replace(/\*/gu, '') + .replace(/-([a-z])/gu, (_, p1) => p1.toUpperCase()) + .replace(/\s*\(strong\)\s*/gu, ''); + it(`ensures ${category}.${cleanKey} matches defined color`, () => { + expect((definedColors as any)[category][cleanKey]).toStrictEqual( + detail.value, + ); + }); + }); + } }); }); diff --git a/src/js/themes/lightTheme/colors.ts b/src/js/themes/lightTheme/colors.ts index 39a54114..9dc1d0a1 100644 --- a/src/js/themes/lightTheme/colors.ts +++ b/src/js/themes/lightTheme/colors.ts @@ -1,110 +1,78 @@ +import { brandColor } from '../../brandColor'; import type { ThemeColors } from '../types'; -/** - * Light theme colors - */ - export const colors: ThemeColors = { background: { - default: '#FFFFFF', - defaultHover: '#FAFAFA', - defaultPressed: '#EBEBEB', - alternative: '#F2F4F6', - alternativeHover: '#EDEFF1', - alternativePressed: '#DFE0E2', - hover: '#00000005', - pressed: '#00000014', + default: brandColor.grey000, // For default neutral backgrounds + alternative: brandColor.grey050, // For secondary neutral backgrounds. + defaultHover: '#f5f5f5', // For "hover" states that use background-default. + defaultPressed: '#ebebeb', // For "pressed" states that use background-alternative. + alternativeHover: '#e7ebee', // For "hover" states that use background-alternative. + alternativePressed: '#dbe0e6', // For "pressed" states that use background-alternative. + hover: '#0000000a', // For "hover" state that use no background fill. + pressed: '#00000014', // For "pressed" state that use no background fill. }, text: { - default: '#24272A', - alternative: '#535A61', - muted: '#BBC0C5', + default: brandColor.grey900, // For default neutral text. + alternative: brandColor.grey500, // For softer contrast neutral text + muted: brandColor.grey300, // For the softest contrast neutral text (not accessible) }, icon: { - default: '#24272A', - alternative: '#6A737D', - muted: '#BBC0C5', + default: brandColor.grey900, // For default neutral icons + alternative: brandColor.grey500, // For softer neutral icons + muted: brandColor.grey300, // For the weakest contrast neutral icons (not accessible) }, border: { - default: '#BBC0C5', - muted: '#D6D9DC', + default: brandColor.grey200, // For soft contrast neutral border + muted: '#bbc0c566', // For the weakest contrast neutral border }, overlay: { - default: '#00000099', - inverse: '#FCFCFC', - alternative: '#000000CC', - }, - shadow: { - default: '#0000001A', + default: '#00000099', // For the default shade of screen + alternative: '#000000cc', // For a stronger shade of screen + inverse: brandColor.grey000, // For elements used on top of overlay/alternative. Used for text, icon or border }, primary: { - default: '#0376C9', - defaultHover: '#0379CE', - defaultPressed: '#036DB9', - alternative: '#0260A4', - muted: '#0376C919', - inverse: '#FFFFFF', - disabled: '#0376C980', - shadow: '#0376C933', - }, - secondary: { - default: '#F66A0A', - alternative: '#BF5208', - muted: '#F66A0A19', - inverse: '#FCFCFC', - disabled: '#F66A0A80', + default: brandColor.blue500, // For interactive, active, and selected semantics. Used for text, background, icon or border + alternative: brandColor.blue600, // For the stronger contrast primary semantic elements. + muted: '#0376c91a', // For the weakest contrast primary semantic backgrounds. + inverse: brandColor.grey000, // For elements used on top of primary/default. Used for text, icon or border + defaultHover: '#036ab5', // For the "hover" state of primary-default elements + defaultPressed: '#025ea1', // For the "pressed" state of primary-default elements }, error: { - default: '#D73847', - defaultHover: '#CD4250', - defaultPressed: '#C63441', - alternative: '#B92534', - muted: '#D7384719', - inverse: '#FFFFFF', - disabled: '#D7384780', - shadow: '#D7384766', + default: brandColor.red500, // For the critical alert semantic elements. Used for text, background, icon or border + alternative: brandColor.red600, // For the stronger contrast error semantic elements. + muted: '#d738471a', // For the weakest contrast critical alert semantic backgrounds. + inverse: brandColor.grey000, // For elements used on top of error/default. Used for text, icon or border + defaultHover: '#d02a3a', // For the "hover" state of error-default elements. + defaultPressed: '#bf2635', // For the "pressed" state of error-default elements. }, warning: { - default: '#BF5208', - defaultHover: '#C2540A', - defaultPressed: '#A24507', - alternative: '#FFC70A', - muted: '#BF520819', - inverse: '#FFFFFF', - disabled: '#FFD33D80', + default: brandColor.yellow500, // For the caution alert semantic elements. Used for text, background, icon or border + muted: '#bf52081a', // For the weakest contrast caution alert semantic backgrounds. + inverse: brandColor.grey000, // For elements used on top of warning/default. Used for text, icon or border + defaultHover: '#ac4a07', // For the "hover" state of warning-default elements + defaultPressed: '#984106', // For the "pressed" state of warning-default elements }, success: { - default: '#1C8234', - defaultHover: '#208838', - defaultPressed: '#1B7431', - alternative: '#1C8234', - muted: '#1C823419', - inverse: '#FFFFFF', - disabled: '#28A74580', + default: brandColor.green500, // For the positive semantic elements. Used for text, background, icon or border + muted: '#1c82341a', // For the weakest contrast positive semantic backgrounds. + inverse: brandColor.grey000, // For elements used on top of success/default. Used for text, icon or border + defaultHover: '#18712d', // For the "hover" state of success-default elements + defaultPressed: '#156127', // For the "pressed" state of success-default elements }, info: { - default: '#0376C9', - alternative: '#0260A4', - muted: '#0376C919', - inverse: '#FFFFFF', - disabled: '#0376C980', - }, - networks: { - goerli: { - default: '#1098FC', - inverse: '#FCFCFC', - }, - localhost: { - default: '#BBC0C5', - inverse: '#FCFCFC', - }, - sepolia: { - default: '#CFB5F0', - inverse: '#FCFCFC', - }, + default: brandColor.blue500, // For informational read-only elements. Used for text, background, icon or border + muted: '#0376c91a', // For the weakest contrast informational semantic backgrounds. + inverse: brandColor.grey000, // For elements used on top of info/default. Used for text, icon or border }, flask: { - default: '#8B45B6', - inverse: '#FCFCFC', + default: brandColor.purple500, // For Flask primary accent color. + inverse: brandColor.grey000, // For elements used on top of flask/default. Used for text, icon or border + }, + shadow: { + default: '#0000001a', // For neutral drop shadow color. + primary: '#0376c933', // For primary drop shadow color. + error: '#ca354266', // For critical/danger drop shadow color. }, }; diff --git a/src/js/themes/lightTheme/lightTheme.test.ts b/src/js/themes/lightTheme/lightTheme.test.ts index 29a8b927..3abfa08f 100644 --- a/src/js/themes/lightTheme/lightTheme.test.ts +++ b/src/js/themes/lightTheme/lightTheme.test.ts @@ -1,13 +1,14 @@ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ import { lightTheme } from './lightTheme'; +const jsonLightThemeTokens = require('../../../figma/lightTheme.json'); const designTokens = require('../../../figma/tokens.json'); describe('Light Theme', () => { - it('color tokens are exported from lightTheme by checking first color token', () => { - expect(lightTheme.colors.background.default).toStrictEqual( - designTokens.light.colors.background.default.value, - ); + it('color tokens are exported from lightTheme by checking a random color token', () => { + expect( + lightTheme.colors.background.defaultHover.toLowerCase(), + ).toStrictEqual(jsonLightThemeTokens.background['default-hover'].value); }); it('typography tokens are exported from lightTheme by checking first typography token', () => { @@ -18,7 +19,7 @@ describe('Light Theme', () => { it('shadow tokens are exported from lightTheme by checking first shadow size object', () => { expect(lightTheme.shadows.size.xs).toStrictEqual({ - shadowColor: designTokens.light.shadows.xs.value.color, + shadowColor: jsonLightThemeTokens.shadow.default.value, shadowOffset: { width: Number(designTokens.light.shadows.xs.value.x), height: Number(designTokens.light.shadows.xs.value.y), diff --git a/src/js/themes/lightTheme/shadows.test.ts b/src/js/themes/lightTheme/shadows.test.ts index ec77d717..32d3d11c 100644 --- a/src/js/themes/lightTheme/shadows.test.ts +++ b/src/js/themes/lightTheme/shadows.test.ts @@ -1,12 +1,13 @@ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ import { shadows } from './shadows'; +const jsonLightThemeTokens = require('../../../figma/lightTheme.json'); const designTokens = require('../../../figma/tokens.json'); describe('Shadows', () => { it('js tokens shadows.size.xs matches figma tokens shadows.xs', () => { - expect(shadows.size.xs.shadowColor).toStrictEqual( - designTokens.light.shadows.xs.value.color, + expect(shadows.size.xs.shadowColor.toLowerCase()).toStrictEqual( + jsonLightThemeTokens.shadow.default.value, ); expect(shadows.size.xs.shadowOffset.width).toStrictEqual( @@ -25,8 +26,8 @@ describe('Shadows', () => { }); it('js tokens shadows.size.sm matches figma tokens shadows.sm', () => { - expect(shadows.size.sm.shadowColor).toStrictEqual( - designTokens.light.shadows.sm.value.color, + expect(shadows.size.sm.shadowColor.toLowerCase()).toStrictEqual( + jsonLightThemeTokens.shadow.default.value, ); expect(shadows.size.sm.shadowOffset.width).toStrictEqual( @@ -45,8 +46,8 @@ describe('Shadows', () => { }); it('js tokens shadows.size.md matches figma tokens shadows.md', () => { - expect(shadows.size.md.shadowColor).toStrictEqual( - designTokens.light.shadows.md.value.color, + expect(shadows.size.md.shadowColor.toLowerCase()).toStrictEqual( + jsonLightThemeTokens.shadow.default.value, ); expect(shadows.size.md.shadowOffset.width).toStrictEqual( @@ -65,8 +66,8 @@ describe('Shadows', () => { }); it('js tokens shadows.size.lg matches figma tokens shadows.lg', () => { - expect(shadows.size.lg.shadowColor).toStrictEqual( - designTokens.light.shadows.lg.value.color, + expect(shadows.size.lg.shadowColor.toLowerCase()).toStrictEqual( + jsonLightThemeTokens.shadow.default.value, ); expect(shadows.size.lg.shadowOffset.width).toStrictEqual( diff --git a/src/js/themes/types.ts b/src/js/themes/types.ts index 91858d58..3334a57e 100644 --- a/src/js/themes/types.ts +++ b/src/js/themes/types.ts @@ -100,19 +100,27 @@ export type ThemeColors = { */ default: string; /** - * {string} overlay.alternative - For a stronger shading layer option behind modality screens + * {string} overlay.alternative - For a stronger shade of screen */ - inverse: string; + alternative: string; /** - * {string} overlay.inverse - [DEPRECATED] Should be used for elements over an overlay + * {string} overlay.inverse - For elements used on top of overlay/alternative. Used for text, icon or border */ - alternative: string; + inverse: string; }; shadow: { /** - * {string} shadow.default - For neutral shadows + * {string} shadow.default - For neutral drop shadow color. */ default: string; + /** + * {string} shadow.primary - For primary drop shadow color. + */ + primary: string; + /** + * {string} shadow.default - For critical/danger drop shadow color. + */ + error: string; }; primary: { /** @@ -139,36 +147,6 @@ export type ThemeColors = { * {string} primary.inverse - For elements used on top of primary/default. (Example: label of primary button, check in a checkbox)disabled state */ inverse: string; - /** - * {string} primary.disabled - [DEPRECATED] Should be used for disabled state - */ - disabled: string; - /** - * {string} primary.shadow - For primary button hover - */ - shadow: string; - }; - secondary: { - /** - * {string} secondary.default - [DEPRECATED] Should be used for any secondary actions. It should not be used for any negative connotations such as warnings or errors as it is quite closely tied to the MetaMask Fox - */ - default: string; - /** - * {string} secondary.alternative - [DEPRECATED] Should be used as an alternative to secondary.default for things such as hover states - */ - alternative: string; - /** - * {string} secondary.muted - [DEPRECATED] It’s a very low contrasting secondary variant for things such as alert backgrounds. secondary.muted and secondary.inverse should not be used together in a foreground and background combination - */ - muted: string; - /** - * {string} secondary.inverse - [DEPRECATED] Should be used only as the foreground element on top of primary/default and primary/alternative. It is intended to be the most contrasting color to primary/default. It should meet all AA and AAA accessibility standards such as the text or icon of a primary button - */ - inverse: string; - /** - * {string} secondary.disabled - [DEPRECATED] Should be used for all disabled secondary action components - */ - disabled: string; }; error: { /** @@ -195,14 +173,6 @@ export type ThemeColors = { * {string} error.inverse - For elements used on top of error/default (Example: label of danger/critical button) */ inverse: string; - /** - * {string} error.disabled - [DEPRECATED] Should be used for disabled state - */ - disabled: string; - /** - * {string} error.shadow - For error danger/critical button hover - */ - shadow: string; }; warning: { /** @@ -217,10 +187,6 @@ export type ThemeColors = { * {string} defaultPressed - For the "pressed" state of interactive elements */ defaultPressed: string; - /** - * {string} warning.alternative - [DEPRECATED] Should be used as an alternative to warning/default for things like hover or pressed states - */ - alternative: string; /** * {string} warning.muted - For lowest contrast background used in warning elements. (Example: notification background) */ @@ -229,10 +195,6 @@ export type ThemeColors = { * {string} warning.inverse - For elements used on top of warning/default. Used for text, icon or border */ inverse: string; - /** - * {string} warning.disabled - [DEPRECATED] Should be used for disabled state - */ - disabled: string; }; success: { /** @@ -247,10 +209,6 @@ export type ThemeColors = { * {string} defaultPressed - For the "pressed" state of interactive elements */ defaultPressed: string; - /** - * {string} success.alternative - [DEPRECATED] Should be used as an alternative to success/default for things like hover or pressed states - */ - alternative: string; /** * {string} success.muted - For lowest contrast background used in success semantic. (Example: notification background) */ @@ -259,20 +217,12 @@ export type ThemeColors = { * {string} success.inverse - For elements used on top of success/default. Used for text, icon or border */ inverse: string; - /** - * {string} success.disabled - [DEPRECATED] Should be used for disabled state - */ - disabled: string; }; info: { /** * {string} info.default - For informational semantic elements. Used for text, background, icon or border */ default: string; - /** - * {string} info.alternative - [DEPRECATED] Should be used as an alternative to info/default for things like hover or pressed states - */ - alternative: string; /** * {string} info.muted - For lowest contrast background used in informational semantic. (Example: notification background) */ @@ -281,42 +231,6 @@ export type ThemeColors = { * {string} info.inverse - For elements used on top of info/default. Used for text, icon or border */ inverse: string; - /** - * {string} info.disabled - [DEPRECATED] Should be used for disabled state - */ - disabled: string; - }; - networks: { - goerli: { - /** - * {string} networks.goerli.default - For goerli test network colored elements - */ - default: string; - /** - * {string} networks.goerli.inverse - For elements used on top of networks/goerli/default - */ - inverse: string; - }; - localhost: { - /** - * {string} networks.localhost.default - For localhost test network colored elements - */ - default: string; - /** - * {string} networks.localhost.inverse - For elements used on top of networks/localhost/default - */ - inverse: string; - }; - sepolia: { - /** - * {string} networks.sepolia.default - For sepolia test network colored elements - */ - default: string; - /** - * {string} networks.sepolia.inverse - For elements used on top of networks/sepolia/default - */ - inverse: string; - }; }; flask: { /**