diff --git a/.nx/version-plans/version-plan-1778082684656.md b/.nx/version-plans/version-plan-1778082684656.md new file mode 100644 index 00000000000..f0c75b4b26c --- /dev/null +++ b/.nx/version-plans/version-plan-1778082684656.md @@ -0,0 +1,6 @@ +--- +gamut-styles: major +gamut: minor +--- + +Updates LXStudio theme to new guidelines diff --git a/packages/gamut-styles/src/__tests__/AssetProvider.test.tsx b/packages/gamut-styles/src/__tests__/AssetProvider.test.tsx index 298c9954a95..7a38ef6fa61 100644 --- a/packages/gamut-styles/src/__tests__/AssetProvider.test.tsx +++ b/packages/gamut-styles/src/__tests__/AssetProvider.test.tsx @@ -12,36 +12,45 @@ jest.mock('../utilities/fontUtils', () => ({ getFonts: jest.fn(), })); -jest.mock('../remoteAssets/fonts', () => ({ - webFonts: { - core: [ - { - filePath: 'https://www.codecademy.com/gamut/apercu-regular-pro', - extensions: ['woff2', 'woff'], - name: 'Apercu', - }, - { - filePath: 'https://www.codecademy.com/gamut/apercu-bold-pro', - extensions: ['woff2', 'woff'], - name: 'Apercu', - weight: 'bold', - }, - ], - percipio: [ - { - filePath: 'https://www.codecademy.com/gamut/roboto-regular', - extensions: ['woff2', 'woff'], - name: 'Roboto', - }, - { - filePath: 'https://www.codecademy.com/gamut/roboto-bold', - extensions: ['woff2', 'woff'], - name: 'Roboto', - weight: 'bold', - }, - ], - }, -})); +jest.mock('../remoteAssets/fonts', () => { + const percipio = [ + { + filePath: 'https://www.codecademy.com/gamut/SkillsoftText-Regular', + extensions: ['woff2', 'woff'], + name: 'Skillsoft Text', + }, + { + filePath: 'https://www.codecademy.com/gamut/roboto-regular', + extensions: ['woff2', 'woff'], + name: 'Roboto', + }, + { + filePath: 'https://www.codecademy.com/gamut/roboto-bold', + extensions: ['woff2', 'woff'], + name: 'Roboto', + weight: 'bold', + }, + ]; + return { + webFonts: { + core: [ + { + filePath: 'https://www.codecademy.com/gamut/apercu-regular-pro', + extensions: ['woff2', 'woff'], + name: 'Apercu', + }, + { + filePath: 'https://www.codecademy.com/gamut/apercu-bold-pro', + extensions: ['woff2', 'woff'], + name: 'Apercu', + weight: 'bold', + }, + ], + percipio, + lxStudio: percipio, + }, + }; +}); const mockGetFonts = require('../utilities/fontUtils').getFonts; diff --git a/packages/gamut-styles/src/__tests__/fontLoading.test.tsx b/packages/gamut-styles/src/__tests__/fontLoading.test.tsx index 782c8bdb109..00bd1026b39 100644 --- a/packages/gamut-styles/src/__tests__/fontLoading.test.tsx +++ b/packages/gamut-styles/src/__tests__/fontLoading.test.tsx @@ -10,24 +10,33 @@ jest.mock('../utilities/fontUtils', () => ({ getFonts: jest.fn(), })); -jest.mock('../remoteAssets/fonts', () => ({ - webFonts: { - core: [ - { - filePath: 'https://www.codecademy.com/gamut/apercu-regular-pro', - extensions: ['woff2', 'woff'], - name: 'Apercu', - }, - ], - percipio: [ - { - filePath: 'https://www.codecademy.com/gamut/roboto-regular', - extensions: ['woff2', 'woff'], - name: 'Roboto', - }, - ], - }, -})); +jest.mock('../remoteAssets/fonts', () => { + const percipio = [ + { + filePath: 'https://www.codecademy.com/gamut/SkillsoftText-Regular', + extensions: ['woff2', 'woff'], + name: 'Skillsoft Text', + }, + { + filePath: 'https://www.codecademy.com/gamut/roboto-regular', + extensions: ['woff2', 'woff'], + name: 'Roboto', + }, + ]; + return { + webFonts: { + core: [ + { + filePath: 'https://www.codecademy.com/gamut/apercu-regular-pro', + extensions: ['woff2', 'woff'], + name: 'Apercu', + }, + ], + percipio, + lxStudio: percipio, + }, + }; +}); const mockGetFonts = require('../utilities/fontUtils').getFonts; diff --git a/packages/gamut-styles/src/remoteAssets/fonts.ts b/packages/gamut-styles/src/remoteAssets/fonts.ts index 4e28b89471a..765c333b878 100644 --- a/packages/gamut-styles/src/remoteAssets/fonts.ts +++ b/packages/gamut-styles/src/remoteAssets/fonts.ts @@ -1,4 +1,4 @@ -import { FontConfig } from '../utilities/fontUtils'; +import type { FontConfig } from '../utilities/fontUtils'; export const FONT_ASSET_PATH = `https://www.codecademy.com/gamut`; @@ -43,7 +43,92 @@ export const core: readonly FontConfig[] = [ }, ]; -export const percipio: readonly FontConfig[] = [ +/** + * Skillsoft Sans (accent) + Skillsoft Text (base). + * Weights 400 / 500 / 700 + italics; 500 uses Medium files for title/bold tokens. + */ +const skillsoftFamilyFonts: readonly FontConfig[] = [ + { + filePath: `${FONT_ASSET_PATH}/SkillsoftText-Regular`, + extensions, + name: 'Skillsoft Text', + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftText-RegularItalic`, + extensions, + name: 'Skillsoft Text', + style: 'italic', + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftText-Medium`, + extensions, + name: 'Skillsoft Text', + weight: 500, + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftText-MediumItalic`, + extensions, + name: 'Skillsoft Text', + weight: 500, + style: 'italic', + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftText-Bold`, + extensions, + name: 'Skillsoft Text', + weight: 700, + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftText-BoldItalic`, + extensions, + name: 'Skillsoft Text', + weight: 700, + style: 'italic', + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftSans-Regular`, + extensions, + name: 'Skillsoft Sans', + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftSans-RegularItalic`, + extensions, + name: 'Skillsoft Sans', + style: 'italic', + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftSans-Medium`, + extensions, + name: 'Skillsoft Sans', + weight: 500, + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftSans-MediumItalic`, + extensions, + name: 'Skillsoft Sans', + weight: 500, + style: 'italic', + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftSans-Bold`, + extensions, + name: 'Skillsoft Sans', + weight: 700, + }, + { + filePath: `${FONT_ASSET_PATH}/SkillsoftSans-BoldItalic`, + extensions, + name: 'Skillsoft Sans', + weight: 700, + style: 'italic', + }, +]; + +/** + * Roboto + Roboto Mono for Percipio `system` and `monospace` theme slots. + * The default weight for bold fonts is 700; Percipio uses 500 for the base bold. + */ +const percipioRobotoFonts: readonly FontConfig[] = [ { filePath: `${FONT_ASSET_PATH}/roboto-regular`, extensions, @@ -55,7 +140,6 @@ export const percipio: readonly FontConfig[] = [ name: 'Roboto', style: 'italic', }, - // The default weight for bold fonts is 700, Percipio uses 500 for the base bold { filePath: `${FONT_ASSET_PATH}/roboto-bold`, extensions, @@ -95,31 +179,10 @@ export const percipio: readonly FontConfig[] = [ }, ]; -export const lxStudio: readonly FontConfig[] = [ - { - filePath: `${FONT_ASSET_PATH}/hanken-grotesk-regular`, - extensions, - name: 'Hanken Grotesk', - }, - { - filePath: `${FONT_ASSET_PATH}/hanken-grotesk-italic`, - extensions, - name: 'Hanken Grotesk', - style: 'italic', - }, - { - filePath: `${FONT_ASSET_PATH}/hanken-grotesk-bold`, - extensions, - name: 'Hanken Grotesk', - weight: 'bold', - }, - { - filePath: `${FONT_ASSET_PATH}/hanken-grotesk-bold-italic`, - extensions, - name: 'Hanken Grotesk', - weight: 'bold', - style: 'italic', - }, +/** Percipio: Skillsoft (accent/base) plus Roboto system + Roboto Mono monospace. */ +export const percipio: readonly FontConfig[] = [ + ...skillsoftFamilyFonts, + ...percipioRobotoFonts, ]; -export const webFonts = { core, percipio, lxStudio } as const; +export const webFonts = { core, percipio, lxStudio: percipio } as const; diff --git a/packages/gamut-styles/src/themes/__tests__/__snapshots__/theme.test.ts.snap b/packages/gamut-styles/src/themes/__tests__/__snapshots__/theme.test.ts.snap index d354180425d..37a4d44f75b 100644 --- a/packages/gamut-styles/src/themes/__tests__/__snapshots__/theme.test.ts.snap +++ b/packages/gamut-styles/src/themes/__tests__/__snapshots__/theme.test.ts.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`themes admin - theme shape 1`] = ` { @@ -1032,6 +1032,533 @@ monospace", } `; +exports[`themes lxStudio - theme shape 1`] = ` +{ + "_getColorValue": [Function], + "_tokens": { + "colors": { + "beige": "#FFF0E5", + "beige-100": "#FFF0E5", + "black": "#000000", + "blue": "#1557FF", + "blue-0": "#F5FCFF", + "blue-100": "#D3F2FF", + "blue-300": "#66C4FF", + "blue-400": "#3388FF", + "blue-500": "#1557FF", + "blue-800": "#1D2340", + "gray-100": "#F5F5F5", + "gray-200": "#EEEEEE", + "gray-300": "#E0E0E0", + "gray-600": "#9E9E9E", + "gray-800": "#616161", + "gray-900": "#424242", + "green": "#008A27", + "green-0": "#F5FFE3", + "green-100": "#EAFDC6", + "green-400": "#AEE938", + "green-700": "#008A27", + "green-900": "#151C07", + "hyper": "#3A10E5", + "hyper-400": "#5533FF", + "hyper-500": "#3A10E5", + "lightBlue": "#66C4FF", + "lightGreen": "#AEE938", + "lxStudioBgPrimary": "#FAFBFC", + "lxStudioSuccess": "#06844F", + "navy": "#10162F", + "navy-100": "rgba(16,22,47,0.04)", + "navy-200": "rgba(16,22,47,0.12)", + "navy-300": "rgba(16,22,47,0.28)", + "navy-400": "rgba(16,22,47,0.47)", + "navy-500": "rgba(16,22,47,0.63)", + "navy-600": "rgba(16,22,47,0.75)", + "navy-700": "rgba(16,22,47,0.86)", + "navy-800": "#10162F", + "navy-900": "#0A0D1C", + "orange": "#FF8C00", + "orange-100": "#FFE8CC", + "orange-500": "#FF8C00", + "paleBlue": "#F5FCFF", + "paleGreen": "#F5FFE3", + "palePink": "#FFF5FF", + "paleRed": "#DC5879", + "paleYellow": "#FFFAE5", + "pink": "#F966FF", + "pink-0": "#FFF5FF", + "pink-400": "#F966FF", + "red": "#E91C11", + "red-0": "#FBF1F0", + "red-300": "#E85D7F", + "red-400": "#DC5879", + "red-500": "#E91C11", + "red-600": "#BE1809", + "red-900": "#280503", + "sapphire": "#1C50BB", + "white": "#ffffff", + "white-100": "rgba(255,255,255,0.04)", + "white-200": "rgba(255,255,255,0.09)", + "white-300": "rgba(255,255,255,0.2)", + "white-400": "rgba(255,255,255,0.35)", + "white-500": "rgba(255,255,255,0.5)", + "white-600": "rgba(255,255,255,0.65)", + "white-700": "rgba(255,255,255,0.8)", + "yellow": "#FFD300", + "yellow-0": "#FFFAE5", + "yellow-400": "#CCA900", + "yellow-500": "#FFD300", + "yellow-900": "#211B00", + }, + "elements": { + "headerHeight": { + "base": "4rem", + "md": "5rem", + }, + "headerZ": 15, + }, + "modes": { + "dark": { + "background": "#10162F", + "background-contrast": "#000000", + "background-current": "#10162F", + "background-disabled": "rgba(255,255,255,0.09)", + "background-error": "#280503", + "background-hover": "rgba(255,255,255,0.09)", + "background-primary": "#0A0D1C", + "background-selected": "rgba(255,255,255,0.04)", + "background-success": "#151C07", + "background-warning": "#211B00", + "border-disabled": "rgba(255,255,255,0.5)", + "border-primary": "#ffffff", + "border-secondary": "rgba(255,255,255,0.65)", + "border-tertiary": "rgba(255,255,255,0.2)", + "danger": "#E85D7F", + "danger-hover": "#DC5879", + "feedback-error": "#E85D7F", + "feedback-success": "#AEE938", + "feedback-warning": "#FFFAE5", + "interface": "#FFD300", + "interface-hover": "#CCA900", + "primary": "#FFD300", + "primary-hover": "#CCA900", + "primary-inverse": "#3A10E5", + "secondary": "#ffffff", + "secondary-hover": "rgba(255,255,255,0.8)", + "shadow-primary": "#ffffff", + "shadow-secondary": "rgba(255,255,255,0.65)", + "text": "#ffffff", + "text-accent": "#FFF0E5", + "text-disabled": "rgba(255,255,255,0.5)", + "text-secondary": "rgba(255,255,255,0.65)", + }, + "light": { + "background": "#ffffff", + "background-contrast": "#ffffff", + "background-current": "#ffffff", + "background-disabled": "rgba(16,22,47,0.12)", + "background-error": "#FBF1F0", + "background-hover": "rgba(16,22,47,0.12)", + "background-primary": "#FAFBFC", + "background-selected": "rgba(16,22,47,0.04)", + "background-success": "#F5FFE3", + "background-warning": "#FFFAE5", + "border-disabled": "rgba(16,22,47,0.28)", + "border-primary": "rgba(16,22,47,0.47)", + "border-secondary": "rgba(16,22,47,0.75)", + "border-tertiary": "#10162F", + "danger": "#E91C11", + "danger-hover": "#BE1809", + "feedback-error": "#BE1809", + "feedback-success": "#06844F", + "feedback-warning": "#FFD300", + "interface": "#3A10E5", + "interface-hover": "#5533FF", + "primary": "#1C50BB", + "primary-hover": "#10162F", + "primary-inverse": "#FFD300", + "secondary": "#10162F", + "secondary-hover": "rgba(16,22,47,0.86)", + "shadow-primary": "rgba(16,22,47,0.12)", + "shadow-secondary": "rgba(16,22,47,0.75)", + "text": "#10162F", + "text-accent": "#0A0D1C", + "text-disabled": "rgba(16,22,47,0.63)", + "text-secondary": "rgba(16,22,47,0.75)", + }, + }, + }, + "_variables": { + "mode": { + "--color-background": "var(--color-white)", + "--color-background-contrast": "var(--color-white)", + "--color-background-current": "var(--color-white)", + "--color-background-disabled": "var(--color-navy-200)", + "--color-background-error": "var(--color-red-0)", + "--color-background-hover": "var(--color-navy-200)", + "--color-background-primary": "var(--color-lxStudioBgPrimary)", + "--color-background-selected": "var(--color-navy-100)", + "--color-background-success": "var(--color-green-0)", + "--color-background-warning": "var(--color-yellow-0)", + "--color-border-disabled": "var(--color-navy-300)", + "--color-border-primary": "var(--color-navy-400)", + "--color-border-secondary": "var(--color-navy-600)", + "--color-border-tertiary": "var(--color-navy-800)", + "--color-danger": "var(--color-red-500)", + "--color-danger-hover": "var(--color-red-600)", + "--color-feedback-error": "var(--color-red-600)", + "--color-feedback-success": "var(--color-lxStudioSuccess)", + "--color-feedback-warning": "var(--color-yellow)", + "--color-interface": "var(--color-hyper-500)", + "--color-interface-hover": "var(--color-hyper-400)", + "--color-primary": "var(--color-sapphire)", + "--color-primary-hover": "var(--color-navy-800)", + "--color-primary-inverse": "var(--color-yellow-500)", + "--color-secondary": "var(--color-navy-800)", + "--color-secondary-hover": "var(--color-navy-700)", + "--color-shadow-primary": "var(--color-navy-200)", + "--color-shadow-secondary": "var(--color-navy-600)", + "--color-text": "var(--color-navy-800)", + "--color-text-accent": "var(--color-navy-900)", + "--color-text-disabled": "var(--color-navy-500)", + "--color-text-secondary": "var(--color-navy-600)", + }, + "root": { + "--color-beige": "#FFF0E5", + "--color-beige-100": "#FFF0E5", + "--color-black": "#000000", + "--color-blue": "#1557FF", + "--color-blue-0": "#F5FCFF", + "--color-blue-100": "#D3F2FF", + "--color-blue-300": "#66C4FF", + "--color-blue-400": "#3388FF", + "--color-blue-500": "#1557FF", + "--color-blue-800": "#1D2340", + "--color-gray-100": "#F5F5F5", + "--color-gray-200": "#EEEEEE", + "--color-gray-300": "#E0E0E0", + "--color-gray-600": "#9E9E9E", + "--color-gray-800": "#616161", + "--color-gray-900": "#424242", + "--color-green": "#008A27", + "--color-green-0": "#F5FFE3", + "--color-green-100": "#EAFDC6", + "--color-green-400": "#AEE938", + "--color-green-700": "#008A27", + "--color-green-900": "#151C07", + "--color-hyper": "#3A10E5", + "--color-hyper-400": "#5533FF", + "--color-hyper-500": "#3A10E5", + "--color-lightBlue": "#66C4FF", + "--color-lightGreen": "#AEE938", + "--color-lxStudioBgPrimary": "#FAFBFC", + "--color-lxStudioSuccess": "#06844F", + "--color-navy": "#10162F", + "--color-navy-100": "rgba(16,22,47,0.04)", + "--color-navy-200": "rgba(16,22,47,0.12)", + "--color-navy-300": "rgba(16,22,47,0.28)", + "--color-navy-400": "rgba(16,22,47,0.47)", + "--color-navy-500": "rgba(16,22,47,0.63)", + "--color-navy-600": "rgba(16,22,47,0.75)", + "--color-navy-700": "rgba(16,22,47,0.86)", + "--color-navy-800": "#10162F", + "--color-navy-900": "#0A0D1C", + "--color-orange": "#FF8C00", + "--color-orange-100": "#FFE8CC", + "--color-orange-500": "#FF8C00", + "--color-paleBlue": "#F5FCFF", + "--color-paleGreen": "#F5FFE3", + "--color-palePink": "#FFF5FF", + "--color-paleRed": "#DC5879", + "--color-paleYellow": "#FFFAE5", + "--color-pink": "#F966FF", + "--color-pink-0": "#FFF5FF", + "--color-pink-400": "#F966FF", + "--color-red": "#E91C11", + "--color-red-0": "#FBF1F0", + "--color-red-300": "#E85D7F", + "--color-red-400": "#DC5879", + "--color-red-500": "#E91C11", + "--color-red-600": "#BE1809", + "--color-red-900": "#280503", + "--color-sapphire": "#1C50BB", + "--color-white": "#ffffff", + "--color-white-100": "rgba(255,255,255,0.04)", + "--color-white-200": "rgba(255,255,255,0.09)", + "--color-white-300": "rgba(255,255,255,0.2)", + "--color-white-400": "rgba(255,255,255,0.35)", + "--color-white-500": "rgba(255,255,255,0.5)", + "--color-white-600": "rgba(255,255,255,0.65)", + "--color-white-700": "rgba(255,255,255,0.8)", + "--color-yellow": "#FFD300", + "--color-yellow-0": "#FFFAE5", + "--color-yellow-400": "#CCA900", + "--color-yellow-500": "#FFD300", + "--color-yellow-900": "#211B00", + "--elements-headerHeight": "4rem", + "--elements-headerZ": 15, + "@media only screen and (min-width: 1024px)": { + "--elements-headerHeight": "5rem", + }, + }, + }, + "borderRadii": { + "full": "999px", + "lg": "12px", + "md": "8px", + "none": "0px", + "sm": "4px", + "xl": "16px", + }, + "borders": { + "1": "1px solid var(--color-border-primary)", + "2": "2px solid var(--color-border-primary)", + }, + "breakpoints": { + "c_base": "@container (min-width: 1px)", + "c_lg": "@container (min-width: 1200px)", + "c_md": "@container (min-width: 1024px)", + "c_sm": "@container (min-width: 768px)", + "c_xl": "@container (min-width: 1440px)", + "c_xs": "@container (min-width: 480px)", + "lg": "@media only screen and (min-width: 1200px)", + "md": "@media only screen and (min-width: 1024px)", + "sm": "@media only screen and (min-width: 768px)", + "xl": "@media only screen and (min-width: 1440px)", + "xs": "@media only screen and (min-width: 480px)", + }, + "colors": { + "background": "var(--color-background)", + "background-contrast": "var(--color-background-contrast)", + "background-current": "var(--color-background-current)", + "background-disabled": "var(--color-background-disabled)", + "background-error": "var(--color-background-error)", + "background-hover": "var(--color-background-hover)", + "background-primary": "var(--color-background-primary)", + "background-selected": "var(--color-background-selected)", + "background-success": "var(--color-background-success)", + "background-warning": "var(--color-background-warning)", + "beige": "var(--color-beige)", + "beige-100": "var(--color-beige-100)", + "black": "var(--color-black)", + "blue": "var(--color-blue)", + "blue-0": "var(--color-blue-0)", + "blue-100": "var(--color-blue-100)", + "blue-300": "var(--color-blue-300)", + "blue-400": "var(--color-blue-400)", + "blue-500": "var(--color-blue-500)", + "blue-800": "var(--color-blue-800)", + "border-disabled": "var(--color-border-disabled)", + "border-primary": "var(--color-border-primary)", + "border-secondary": "var(--color-border-secondary)", + "border-tertiary": "var(--color-border-tertiary)", + "danger": "var(--color-danger)", + "danger-hover": "var(--color-danger-hover)", + "feedback-error": "var(--color-feedback-error)", + "feedback-success": "var(--color-feedback-success)", + "feedback-warning": "var(--color-feedback-warning)", + "gray-100": "var(--color-gray-100)", + "gray-200": "var(--color-gray-200)", + "gray-300": "var(--color-gray-300)", + "gray-600": "var(--color-gray-600)", + "gray-800": "var(--color-gray-800)", + "gray-900": "var(--color-gray-900)", + "green": "var(--color-green)", + "green-0": "var(--color-green-0)", + "green-100": "var(--color-green-100)", + "green-400": "var(--color-green-400)", + "green-700": "var(--color-green-700)", + "green-900": "var(--color-green-900)", + "hyper": "var(--color-hyper)", + "hyper-400": "var(--color-hyper-400)", + "hyper-500": "var(--color-hyper-500)", + "interface": "var(--color-interface)", + "interface-hover": "var(--color-interface-hover)", + "lightBlue": "var(--color-lightBlue)", + "lightGreen": "var(--color-lightGreen)", + "lxStudioBgPrimary": "var(--color-lxStudioBgPrimary)", + "lxStudioSuccess": "var(--color-lxStudioSuccess)", + "navy": "var(--color-navy)", + "navy-100": "var(--color-navy-100)", + "navy-200": "var(--color-navy-200)", + "navy-300": "var(--color-navy-300)", + "navy-400": "var(--color-navy-400)", + "navy-500": "var(--color-navy-500)", + "navy-600": "var(--color-navy-600)", + "navy-700": "var(--color-navy-700)", + "navy-800": "var(--color-navy-800)", + "navy-900": "var(--color-navy-900)", + "orange": "var(--color-orange)", + "orange-100": "var(--color-orange-100)", + "orange-500": "var(--color-orange-500)", + "paleBlue": "var(--color-paleBlue)", + "paleGreen": "var(--color-paleGreen)", + "palePink": "var(--color-palePink)", + "paleRed": "var(--color-paleRed)", + "paleYellow": "var(--color-paleYellow)", + "pink": "var(--color-pink)", + "pink-0": "var(--color-pink-0)", + "pink-400": "var(--color-pink-400)", + "primary": "var(--color-primary)", + "primary-hover": "var(--color-primary-hover)", + "primary-inverse": "var(--color-primary-inverse)", + "red": "var(--color-red)", + "red-0": "var(--color-red-0)", + "red-300": "var(--color-red-300)", + "red-400": "var(--color-red-400)", + "red-500": "var(--color-red-500)", + "red-600": "var(--color-red-600)", + "red-900": "var(--color-red-900)", + "sapphire": "var(--color-sapphire)", + "secondary": "var(--color-secondary)", + "secondary-hover": "var(--color-secondary-hover)", + "shadow-primary": "var(--color-shadow-primary)", + "shadow-secondary": "var(--color-shadow-secondary)", + "text": "var(--color-text)", + "text-accent": "var(--color-text-accent)", + "text-disabled": "var(--color-text-disabled)", + "text-secondary": "var(--color-text-secondary)", + "white": "var(--color-white)", + "white-100": "var(--color-white-100)", + "white-200": "var(--color-white-200)", + "white-300": "var(--color-white-300)", + "white-400": "var(--color-white-400)", + "white-500": "var(--color-white-500)", + "white-600": "var(--color-white-600)", + "white-700": "var(--color-white-700)", + "yellow": "var(--color-yellow)", + "yellow-0": "var(--color-yellow-0)", + "yellow-400": "var(--color-yellow-400)", + "yellow-500": "var(--color-yellow-500)", + "yellow-900": "var(--color-yellow-900)", + }, + "elements": { + "headerHeight": "var(--elements-headerHeight)", + "headerZ": "var(--elements-headerZ)", + }, + "fontFamily": { + "accent": ""Skillsoft Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", +"Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", +sans-serif", + "base": ""Skillsoft Text", -apple-system, BlinkMacSystemFont, "Segoe UI", +"Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", +sans-serif", + "monospace": "Monaco, Menlo, "Ubuntu Mono", "Droid Sans Mono", Consolas, +monospace", + "system": "-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", +"Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif", + }, + "fontSize": { + "14": "0.875rem", + "16": "1rem", + "18": "1.125rem", + "20": "1.25rem", + "22": "1.375rem", + "26": "1.625rem", + "34": "2.125rem", + "44": "2.75rem", + "64": "4rem", + }, + "fontWeight": { + "400": 400, + "500": 500, + "700": 700, + "base": 400, + "bold": 500, + "title": 500, + }, + "lineHeight": { + "base": 1.5, + "spacedTitle": 1.3, + "title": 1.2, + }, + "mode": "light", + "modes": { + "dark": { + "background": "navy-800", + "background-contrast": "black", + "background-current": "navy-800", + "background-disabled": "white-200", + "background-error": "red-900", + "background-hover": "white-200", + "background-primary": "navy-900", + "background-selected": "white-100", + "background-success": "green-900", + "background-warning": "yellow-900", + "border-disabled": "white-500", + "border-primary": "white", + "border-secondary": "white-600", + "border-tertiary": "white-300", + "danger": "red-300", + "danger-hover": "red-400", + "feedback-error": "red-300", + "feedback-success": "green-400", + "feedback-warning": "yellow-0", + "interface": "yellow-500", + "interface-hover": "yellow-400", + "primary": "yellow-500", + "primary-hover": "yellow-400", + "primary-inverse": "hyper-500", + "secondary": "white", + "secondary-hover": "white-700", + "shadow-primary": "white", + "shadow-secondary": "white-600", + "text": "white", + "text-accent": "beige", + "text-disabled": "white-500", + "text-secondary": "white-600", + }, + "light": { + "background": "white", + "background-contrast": "white", + "background-current": "white", + "background-disabled": "navy-200", + "background-error": "red-0", + "background-hover": "navy-200", + "background-primary": "lxStudioBgPrimary", + "background-selected": "navy-100", + "background-success": "green-0", + "background-warning": "yellow-0", + "border-disabled": "navy-300", + "border-primary": "navy-400", + "border-secondary": "navy-600", + "border-tertiary": "navy-800", + "danger": "red-500", + "danger-hover": "red-600", + "feedback-error": "red-600", + "feedback-success": "lxStudioSuccess", + "feedback-warning": "yellow", + "interface": "hyper-500", + "interface-hover": "hyper-400", + "primary": "sapphire", + "primary-hover": "navy-800", + "primary-inverse": "yellow-500", + "secondary": "navy-800", + "secondary-hover": "navy-700", + "shadow-primary": "navy-200", + "shadow-secondary": "navy-600", + "text": "navy-800", + "text-accent": "navy-900", + "text-disabled": "navy-500", + "text-secondary": "navy-600", + }, + }, + "name": "lxStudio", + "spacing": { + "0": 0, + "12": "0.75rem", + "16": "1rem", + "24": "1.5rem", + "32": "2rem", + "4": "0.25rem", + "40": "2.5rem", + "48": "3rem", + "64": "4rem", + "8": "0.5rem", + "96": "6rem", + }, +} +`; + exports[`themes platform - theme shape 1`] = ` { "_getColorValue": [Function], diff --git a/packages/gamut-styles/src/themes/__tests__/theme.test.ts b/packages/gamut-styles/src/themes/__tests__/theme.test.ts index 8ad761e01b8..00a2ff34686 100644 --- a/packages/gamut-styles/src/themes/__tests__/theme.test.ts +++ b/packages/gamut-styles/src/themes/__tests__/theme.test.ts @@ -1,5 +1,6 @@ import { adminTheme } from '../admin'; import { coreTheme } from '../core'; +import { lxStudioTheme } from '../lxStudio'; import { platformTheme } from '../platform'; describe('themes', () => { @@ -7,5 +8,6 @@ describe('themes', () => { ['core', coreTheme], ['platform', platformTheme], ['admin', adminTheme], + ['lxStudio', lxStudioTheme], ])(`%s - theme shape`, (_, theme) => expect(theme).toMatchSnapshot()); }); diff --git a/packages/gamut-styles/src/themes/lxStudio.ts b/packages/gamut-styles/src/themes/lxStudio.ts index b37c060884c..7b787cdc4fb 100644 --- a/packages/gamut-styles/src/themes/lxStudio.ts +++ b/packages/gamut-styles/src/themes/lxStudio.ts @@ -1,10 +1,11 @@ import { createTheme } from '@codecademy/variance'; import { - fontLxStudio, fontMonospace, fontSystem, + fontWeightMediumTitle, lxStudioPalette, + percipioFontFamily, } from '../variables'; import { coreTheme } from './core'; @@ -14,8 +15,8 @@ import { coreTheme } from './core'; */ const lxStudioFontFamily = { - accent: fontLxStudio, - base: fontLxStudio, + accent: percipioFontFamily.accent, + base: percipioFontFamily.base, monospace: fontMonospace, system: fontSystem, } as const; @@ -33,6 +34,7 @@ export const lxStudioTheme = createTheme({ ...coreTheme, borderRadii: lxStudioBorderRadii, fontFamily: lxStudioFontFamily, + fontWeight: fontWeightMediumTitle, }) .addColors(lxStudioPalette) .addColorModes('light', { @@ -48,8 +50,8 @@ export const lxStudioTheme = createTheme({ primary: 'navy-200', }, primary: { - _: 'lxStudioPurple', - hover: 'lxStudioPurpleHover', + _: 'sapphire', + hover: 'navy-800', }, interface: { _: 'hyper-500', @@ -67,4 +69,4 @@ export const lxStudioTheme = createTheme({ export type LxStudioThemeShape = typeof lxStudioTheme; -export interface LxStudioTheme extends LxStudioThemeShape {} +export type LxStudioTheme = LxStudioThemeShape; diff --git a/packages/gamut-styles/src/themes/percipio.ts b/packages/gamut-styles/src/themes/percipio.ts index f5903dc904c..8ad0013945d 100644 --- a/packages/gamut-styles/src/themes/percipio.ts +++ b/packages/gamut-styles/src/themes/percipio.ts @@ -1,18 +1,16 @@ import { createTheme } from '@codecademy/variance'; -import { percipioFontFamily, percipioPalette } from '../variables'; +import { + fontWeightMediumTitle, + percipioFontFamily, + percipioPalette, +} from '../variables'; import { coreTheme } from './core'; export const percipioTheme = createTheme({ ...coreTheme, fontFamily: percipioFontFamily, - fontWeight: { - base: 400, - title: 500, - bold: 500, - 700: 700, - 400: 400, - }, + fontWeight: fontWeightMediumTitle, }) .addColors(percipioPalette) .addColorModes('light', { @@ -40,7 +38,7 @@ export const percipioTheme = createTheme({ secondary: 'navy-400', }, primary: { - _: 'percipioActionPrimary', + _: 'sapphire', hover: 'percipioActionPrimaryHover', inverse: 'white', }, @@ -53,7 +51,7 @@ export const percipioTheme = createTheme({ hover: 'percipioActionDangerHover', }, interface: { - _: 'percipioActionPrimary', + _: 'sapphire', hover: 'percipioActionPrimaryHover', }, border: { diff --git a/packages/gamut-styles/src/utilities/__tests__/fontUtils.test.ts b/packages/gamut-styles/src/utilities/__tests__/fontUtils.test.ts index f10a302a0ed..75880cdfd93 100644 --- a/packages/gamut-styles/src/utilities/__tests__/fontUtils.test.ts +++ b/packages/gamut-styles/src/utilities/__tests__/fontUtils.test.ts @@ -1,36 +1,39 @@ import { webFonts } from '../../remoteAssets/fonts'; import { getFonts } from '../fontUtils'; -jest.mock('../../remoteAssets/fonts', () => ({ - webFonts: { - core: [ - { - filePath: 'https://www.codecademy.com/gamut/apercu-regular-pro', - extensions: ['woff2', 'woff'], - name: 'Apercu', - }, - { - filePath: 'https://www.codecademy.com/gamut/apercu-bold-pro', - extensions: ['woff2', 'woff'], - name: 'Apercu', - weight: 'bold', - }, - ], - percipio: [ - { - filePath: 'https://www.codecademy.com/gamut/roboto-regular', - extensions: ['woff2', 'woff'], - name: 'Roboto', - }, - { - filePath: 'https://www.codecademy.com/gamut/roboto-bold', - extensions: ['woff2', 'woff'], - name: 'Roboto', - weight: 'bold', - }, - ], - }, -})); +jest.mock('../../remoteAssets/fonts', () => { + const percipio = [ + { + filePath: 'https://www.codecademy.com/gamut/SkillsoftText-Regular', + extensions: ['woff2', 'woff'], + name: 'Skillsoft Text', + }, + { + filePath: 'https://www.codecademy.com/gamut/roboto-regular', + extensions: ['woff2', 'woff'], + name: 'Roboto', + }, + ]; + return { + webFonts: { + core: [ + { + filePath: 'https://www.codecademy.com/gamut/apercu-regular-pro', + extensions: ['woff2', 'woff'], + name: 'Apercu', + }, + { + filePath: 'https://www.codecademy.com/gamut/apercu-bold-pro', + extensions: ['woff2', 'woff'], + name: 'Apercu', + weight: 'bold', + }, + ], + percipio, + lxStudio: percipio, + }, + }; +}); describe('fontUtils', () => { describe('getFonts', () => { @@ -55,6 +58,11 @@ describe('fontUtils', () => { expect(fonts).toBe(webFonts.percipio); }); + it('should return percipio fonts for lxStudio theme', () => { + const fonts = getFonts('lxStudio'); + expect(fonts).toBe(webFonts.percipio); + }); + it('should return core fonts for core theme', () => { const fonts = getFonts('core'); expect(fonts).toBe(webFonts.core); @@ -99,6 +107,7 @@ describe('fontUtils', () => { webFonts: { core: undefined, percipio: webFonts.percipio, + lxStudio: webFonts.percipio, }, })); diff --git a/packages/gamut-styles/src/variables/colors.ts b/packages/gamut-styles/src/variables/colors.ts index 51196adbb6f..38001718876 100644 --- a/packages/gamut-styles/src/variables/colors.ts +++ b/packages/gamut-styles/src/variables/colors.ts @@ -164,11 +164,13 @@ export const platformPalette = { * LX Studio Colors */ +/** Primary brand blue; used by LX Studio and Percipio theme `primary` tokens */ +export const sapphire = '#1C50BB'; + export const lxStudioColors = { lxStudioSuccess: '#06844F', lxStudioBgPrimary: '#FAFBFC', - lxStudioPurple: '#5628FE', - lxStudioPurpleHover: '#7955FC', + sapphire, } as const; export const lxStudioPalette = { @@ -194,7 +196,7 @@ export const percipioColors = { percipioBgError: '#FFF1F5', // Action colors - percipioActionPrimary: '#0073C4', + sapphire, percipioActionPrimaryHover: '#141C36', percipioActionSecondary: '#6A6E75', percipioActionSecondaryHover: 'rgba(106, 110, 117, 0.86)', @@ -206,6 +208,8 @@ export const percipioColors = { // Multiuse colors percipioDanger: '#B83C3C', + + /** Shared with LX Studio; `primary` color mode resolves here */ } as const; export const percipioPalette = { diff --git a/packages/gamut-styles/src/variables/typography.ts b/packages/gamut-styles/src/variables/typography.ts index e096c1b342a..2bd2b4001c1 100644 --- a/packages/gamut-styles/src/variables/typography.ts +++ b/packages/gamut-styles/src/variables/typography.ts @@ -14,7 +14,11 @@ monospace`; export const fontSystem = `-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif`; -export const fontLxStudio = `"Hanken Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", +export const fontPercipioAccent = `"Skillsoft Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", +"Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", +sans-serif`; + +export const fontPercipioBase = `"Skillsoft Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif`; @@ -50,9 +54,17 @@ export const fontWeight = { 400: 400, } as const; +/** Title/bold semantic tokens use 500 (Medium), matching Skillsoft + Percipio Roboto webfonts. */ +export const fontWeightMediumTitle = { + ...fontWeight, + title: 500, + bold: 500, + 500: 500, +} as const; + export const percipioFontFamily = { - accent: '"Roboto", sans-serif', - base: '"Roboto", sans-serif', + accent: fontPercipioAccent, + base: fontPercipioBase, monospace: '"Roboto Mono", monospace', system: '"Roboto", sans-serif', } as const; diff --git a/packages/gamut/src/Menu/elements.tsx b/packages/gamut/src/Menu/elements.tsx index 6b2773b566a..f8eea4af20d 100644 --- a/packages/gamut/src/Menu/elements.tsx +++ b/packages/gamut/src/Menu/elements.tsx @@ -143,10 +143,10 @@ const activeStates = system.states({ bg: 'background-selected', }, active: { - fontWeight: 700, + fontWeight: 'title', }, 'active-navlink': { - fontWeight: 700, + fontWeight: 'title', bg: 'background-selected', [Selectors.BEFORE]: { content: "''", diff --git a/packages/gamut/src/Tabs/TabButton.tsx b/packages/gamut/src/Tabs/TabButton.tsx index 8a99b1566b1..0cbaf3f2582 100644 --- a/packages/gamut/src/Tabs/TabButton.tsx +++ b/packages/gamut/src/Tabs/TabButton.tsx @@ -15,7 +15,7 @@ export interface TabButtonProps TabElementStyleProps {} const tabSelectedStyles = { - fontWeight: 700, + fontWeight: 'title', pt: 12, pb: 8, borderBottomWidth: 4, diff --git a/packages/styleguide/.storybook/components/Elements/DocsContainer.tsx b/packages/styleguide/.storybook/components/Elements/DocsContainer.tsx index 0e55152fda5..03c19bdc0c8 100644 --- a/packages/styleguide/.storybook/components/Elements/DocsContainer.tsx +++ b/packages/styleguide/.storybook/components/Elements/DocsContainer.tsx @@ -19,7 +19,7 @@ import { import { ThemeProvider } from 'storybook/theming'; import { useMemo } from 'react'; import { HelmetProvider } from 'react-helmet-async'; -import theme from '../../theming/GamutTheme'; +import { createGamutDocsTheme } from '../../theming/GamutTheme'; import { createTheme } from '@codecademy/variance'; export const storybookTheme = createTheme(coreTheme) .addColors(platformPalette) @@ -74,8 +74,17 @@ export const DocsContainer: React.FC<{ }; }, [storyId, globalTheme]); + const storybookDocsChromeTheme = useMemo( + () => createGamutDocsTheme(currentTheme.fontFamily.base), + [currentTheme] + ); + return ( - + = ({ diff --git a/packages/styleguide/.storybook/theming/GamutTheme.ts b/packages/styleguide/.storybook/theming/GamutTheme.ts index f6340392f62..5698c91919d 100644 --- a/packages/styleguide/.storybook/theming/GamutTheme.ts +++ b/packages/styleguide/.storybook/theming/GamutTheme.ts @@ -9,36 +9,48 @@ import logo from '../assets/logo.svg'; const isLocalhost = globalThis.location?.toString().includes('localhost'); -export default create({ - base: 'light', - brandTitle: isLocalhost ? 'Gamut Local' : 'Gamut', - brandImage: logo, - brandUrl: '/', - fontBase: gamutTheme.fontFamily.base, - - // - colorPrimary: trueColors.hyper, - colorSecondary: trueColors.navy, - - // UI - appBg: trueColors.white, - appContentBg: isLocalhost ? trueColors.beige : trueColors.paleBlue, - appBorderColor: trueColors.navy, - appBorderRadius: 4, - - // Text colors - textColor: trueColors.navy, - textInverseColor: trueColors.white, - textMutedColor: coreSwatches.gray[800], - - // Toolbar default and active colors - barTextColor: coreSwatches.gray[600], - barSelectedColor: trueColors.navy, - barBg: trueColors.white, - - // Form colors - inputBg: trueColors.white, - inputBorder: trueColors.navy, - inputTextColor: trueColors.navy, - inputBorderRadius: 2, -}); +/** + * Storybook docs chrome (`parameters.docs.theme`) uses `fontBase` for MDX canvas + * typography. It must match the toolbar-selected Gamut theme’s `fontFamily.base` + * (see DocsContainer); otherwise e.g. LX Studio shows Skillsoft Text on `body` + * from Reboot but Apercu inside addon-docs div rules. + */ +export function createGamutDocsTheme( + fontBase: string = gamutTheme.fontFamily.base +) { + return create({ + base: 'light', + brandTitle: isLocalhost ? 'Gamut Local' : 'Gamut', + brandImage: logo, + brandUrl: '/', + fontBase, + + // + colorPrimary: trueColors.hyper, + colorSecondary: trueColors.navy, + + // UI + appBg: trueColors.white, + appContentBg: isLocalhost ? trueColors.beige : trueColors.paleBlue, + appBorderColor: trueColors.navy, + appBorderRadius: 4, + + // Text colors + textColor: trueColors.navy, + textInverseColor: trueColors.white, + textMutedColor: coreSwatches.gray[800], + + // Toolbar default and active colors + barTextColor: coreSwatches.gray[600], + barSelectedColor: trueColors.navy, + barBg: trueColors.white, + + // Form colors + inputBg: trueColors.white, + inputBorder: trueColors.navy, + inputTextColor: trueColors.navy, + inputBorderRadius: 2, + }); +} + +export default createGamutDocsTheme(); diff --git a/packages/styleguide/src/lib/Foundations/Theme/LXStudioTheme.mdx b/packages/styleguide/src/lib/Foundations/Theme/LXStudioTheme.mdx index cff103a3988..ac141100995 100644 --- a/packages/styleguide/src/lib/Foundations/Theme/LXStudioTheme.mdx +++ b/packages/styleguide/src/lib/Foundations/Theme/LXStudioTheme.mdx @@ -30,12 +30,12 @@ If you are using the LX Studio Theme via the Gamut theme provider in your app (i import { css } from '@codecademy/gamut-styles'; import styled from '@emotion/styled'; -const Box = styled.div(css({ bg: 'lxStudioPurple', p: 4 })); // our system props inherently use the current theme +const Box = styled.div(css({ bg: 'sapphire', p: 4 })); // our system props inherently use the current theme const styles = styled.div` blue: ${({ theme }) => theme.colors - .lxStudioPurple}; // theme here refers to the current theme, which is the LX Studio theme + .sapphire}; // theme here refers to the current theme, which is the LX Studio theme `; ``` @@ -46,12 +46,12 @@ import { css } from '@emotion/react'; import { lxStudioTheme, theme } from '@codecademy/gamut-styles'; const myStyles = css` - color: ${lxStudioTheme.colors.lxStudioPurple}; + color: ${lxStudioTheme.colors.sapphire}; `; const notWorkingStyles = css` color: ${theme.colors - .lxStudioPurple}; // teal does not exist in the Core Theme colors so this does not work + .sapphire}; // sapphire does not exist on the Core Theme colors so this does not work `; ``` diff --git a/packages/styleguide/src/lib/Foundations/Theme/PercipioTheme.mdx b/packages/styleguide/src/lib/Foundations/Theme/PercipioTheme.mdx index 0ff44224640..21ad62833cf 100644 --- a/packages/styleguide/src/lib/Foundations/Theme/PercipioTheme.mdx +++ b/packages/styleguide/src/lib/Foundations/Theme/PercipioTheme.mdx @@ -93,6 +93,6 @@ Percipio currently only supports `light` mode. **Key**: `fontFamily` -The Percipio theme uses Roboto fonts for all font families to provide a consistent typography experience. +The Percipio theme uses Skillsoft Sans for accent text and Skillsoft Text for body text. Roboto Mono is used for monospace, and Roboto sans-serif for the `system` font family slot. diff --git a/packages/styleguide/src/lib/Organisms/Lists & Tables/List/List.stories.tsx b/packages/styleguide/src/lib/Organisms/Lists & Tables/List/List.stories.tsx index 79b6237c40f..cdd5feba009 100644 --- a/packages/styleguide/src/lib/Organisms/Lists & Tables/List/List.stories.tsx +++ b/packages/styleguide/src/lib/Organisms/Lists & Tables/List/List.stories.tsx @@ -317,7 +317,7 @@ export const CondensedSpacingGuide: Story = { {rows.map(({ name, role, ship }, i, _, key = `example-row-${i}`) => ( - + {name} @@ -391,7 +391,7 @@ export const CondensedTableGuide: Story = { {rows.map(({ name, role, ship }, i, _, key = `example-row-${i}`) => ( - + {name} diff --git a/packages/styleguide/src/lib/Organisms/Lists & Tables/List/ListCol/ListCol.stories.tsx b/packages/styleguide/src/lib/Organisms/Lists & Tables/List/ListCol/ListCol.stories.tsx index 4cc200f8bcd..422e19c8393 100644 --- a/packages/styleguide/src/lib/Organisms/Lists & Tables/List/ListCol/ListCol.stories.tsx +++ b/packages/styleguide/src/lib/Organisms/Lists & Tables/List/ListCol/ListCol.stories.tsx @@ -110,7 +110,7 @@ export const HorizontalScrolling: ListCompositionStory = { {rows.map(({ name, role, ship }, i, _, key = `example-row-${i}`) => ( - + {name} @@ -223,7 +223,7 @@ export const Responsive: ListCompositionStory = { - + Ordered List Header