From ed90f003b7f0d2ae6886e1a4a6cbc85a4cff62ad Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Thu, 10 Jul 2025 14:40:13 -0400 Subject: [PATCH 01/14] colorTextOnPrimaryBackground -> colorPrimaryForeground --- .../clerk-js/src/ui/common/ProviderInitialIcon.tsx | 2 +- .../customizables/__tests__/parseAppearance.test.tsx | 10 +++++----- .../clerk-js/src/ui/customizables/parseVariables.ts | 6 +++++- packages/clerk-js/src/ui/foundations/colors.ts | 2 +- packages/clerk-js/src/ui/primitives/Badge.tsx | 2 +- packages/clerk-js/src/ui/primitives/Button.tsx | 2 +- .../clerk-js/src/ui/primitives/NotificationBadge.tsx | 2 +- packages/clerk-js/src/ui/primitives/Text.tsx | 2 +- packages/themes/src/themes/dark.ts | 2 +- packages/themes/src/themes/shadesOfPurple.ts | 2 +- packages/types/src/appearance.ts | 7 +++++++ 11 files changed, 25 insertions(+), 14 deletions(-) diff --git a/packages/clerk-js/src/ui/common/ProviderInitialIcon.tsx b/packages/clerk-js/src/ui/common/ProviderInitialIcon.tsx index 4cf2d30ca5d..c179a6b0d66 100644 --- a/packages/clerk-js/src/ui/common/ProviderInitialIcon.tsx +++ b/packages/clerk-js/src/ui/common/ProviderInitialIcon.tsx @@ -22,7 +22,7 @@ export const ProviderInitialIcon = (props: ProviderInitialIconProps) => { width: t.space.$4, height: t.space.$4, borderRadius: t.radii.$sm, - color: t.colors.$colorTextOnPrimaryBackground, + color: t.colors.$colorPrimaryForeground, backgroundColor: t.colors.$primary500, })} {...rest} diff --git a/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx b/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx index bc3982c82b0..ccda943c167 100644 --- a/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx +++ b/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx @@ -18,7 +18,7 @@ const themeA = { colorInputBackground: themeAColor, colorInputText: themeAColor, colorText: themeAColor, - colorTextOnPrimaryBackground: themeAColor, + colorPrimaryForeground: themeAColor, colorTextSecondary: themeAColor, borderRadius: '1rem', fontFamily: 'Comic Sans', @@ -40,7 +40,7 @@ const themeB = { colorInputBackground: themeBColor, colorInputText: themeBColor, colorText: themeBColor, - colorTextOnPrimaryBackground: themeBColor, + colorPrimaryForeground: themeBColor, colorTextSecondary: themeBColor, borderRadius: '2rem', fontFamily: 'Arial', @@ -82,7 +82,7 @@ describe('AppearanceProvider internalTheme flows', () => { expect(result.current.parsedInternalTheme.colors.$colorInputBackground).toBe(knownColors[themeAColor]); expect(result.current.parsedInternalTheme.colors.$colorInputText).toBe(knownColors[themeAColor]); expect(result.current.parsedInternalTheme.colors.$colorText).toBe(knownColors[themeAColor]); - expect(result.current.parsedInternalTheme.colors.$colorTextOnPrimaryBackground).toBe(knownColors[themeAColor]); + expect(result.current.parsedInternalTheme.colors.$colorPrimaryForeground).toBe(knownColors[themeAColor]); expect(result.current.parsedInternalTheme.colors.$colorTextSecondary).toBe(knownColors[themeAColor]); expect(result.current.parsedInternalTheme.radii.$md).toBe(themeA.variables.borderRadius); expect(result.current.parsedInternalTheme.fonts.$main).toBe(themeA.variables.fontFamily); @@ -112,7 +112,7 @@ describe('AppearanceProvider internalTheme flows', () => { expect(result.current.parsedInternalTheme.colors.$colorInputBackground).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorInputText).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorText).toBe(knownColors[themeBColor]); - expect(result.current.parsedInternalTheme.colors.$colorTextOnPrimaryBackground).toBe(knownColors[themeBColor]); + expect(result.current.parsedInternalTheme.colors.$colorPrimaryForeground).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorTextSecondary).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.radii.$md).toBe(themeB.variables.borderRadius); expect(result.current.parsedInternalTheme.fonts.$main).toBe(themeB.variables.fontFamily); @@ -143,7 +143,7 @@ describe('AppearanceProvider internalTheme flows', () => { expect(result.current.parsedInternalTheme.colors.$colorInputBackground).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorInputText).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorText).toBe(knownColors[themeBColor]); - expect(result.current.parsedInternalTheme.colors.$colorTextOnPrimaryBackground).toBe(knownColors[themeBColor]); + expect(result.current.parsedInternalTheme.colors.$colorPrimaryForeground).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorTextSecondary).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.radii.$md).toBe(themeB.variables.borderRadius); expect(result.current.parsedInternalTheme.fonts.$main).toBe(themeB.variables.fontFamily); diff --git a/packages/clerk-js/src/ui/customizables/parseVariables.ts b/packages/clerk-js/src/ui/customizables/parseVariables.ts index 9a8a49017a7..89c39085f83 100644 --- a/packages/clerk-js/src/ui/customizables/parseVariables.ts +++ b/packages/clerk-js/src/ui/customizables/parseVariables.ts @@ -33,7 +33,11 @@ export const createColorScales = (theme: Theme) => { ...successAlphaScale, ...warningAlphaScale, primaryHover: colors.adjustForLightness(primaryScale?.primary500), - colorTextOnPrimaryBackground: colors.toHslaString(variables.colorTextOnPrimaryBackground), + colorPrimaryForeground: variables.colorPrimaryForeground + ? colors.toHslaString(variables.colorPrimaryForeground) + : variables.colorTextOnPrimaryBackground + ? colors.toHslaString(variables.colorTextOnPrimaryBackground) + : undefined, colorText: colors.toHslaString(variables.colorText), colorTextSecondary: colors.toHslaString(variables.colorTextSecondary) || colors.makeTransparent(variables.colorText, 0.35), diff --git a/packages/clerk-js/src/ui/foundations/colors.ts b/packages/clerk-js/src/ui/foundations/colors.ts index 773294f9c04..0138ea65049 100644 --- a/packages/clerk-js/src/ui/foundations/colors.ts +++ b/packages/clerk-js/src/ui/foundations/colors.ts @@ -86,7 +86,7 @@ const colors = Object.freeze({ colorText, colorTextSecondary, colorInputText: clerkCssVar('color-input-text', '#131316'), - colorTextOnPrimaryBackground: clerkCssVar('color-text-on-primary-background', 'white'), + colorPrimaryForeground: clerkCssVar('color-primary-foreground', 'white'), colorShimmer: clerkCssVar('color-shimmer', 'rgba(255, 255, 255, 0.36)'), transparent: 'transparent', white: 'white', diff --git a/packages/clerk-js/src/ui/primitives/Badge.tsx b/packages/clerk-js/src/ui/primitives/Badge.tsx index f0636b485d4..d196bf0a4aa 100644 --- a/packages/clerk-js/src/ui/primitives/Badge.tsx +++ b/packages/clerk-js/src/ui/primitives/Badge.tsx @@ -27,7 +27,7 @@ const { applyVariants, filterProps } = createVariants(theme => ({ [vars.borderColor]: theme.colors.$neutralAlpha150, }, secondary: { - [vars.accent]: theme.colors.$colorTextOnPrimaryBackground, + [vars.accent]: theme.colors.$colorPrimaryForeground, [vars.bg]: theme.colors.$primary500, [vars.borderColor]: theme.colors.$primary500, }, diff --git a/packages/clerk-js/src/ui/primitives/Button.tsx b/packages/clerk-js/src/ui/primitives/Button.tsx index b012d4d3e66..7665f11b6de 100644 --- a/packages/clerk-js/src/ui/primitives/Button.tsx +++ b/packages/clerk-js/src/ui/primitives/Button.tsx @@ -51,7 +51,7 @@ const { applyVariants, filterProps } = createVariants( [vars.accent]: theme.colors.$primary500, [vars.accentHover]: theme.colors.$primaryHover, [vars.border]: theme.colors.$primary500, - [vars.accentContrast]: theme.colors.$colorTextOnPrimaryBackground, + [vars.accentContrast]: theme.colors.$colorPrimaryForeground, [vars.alpha]: theme.colors.$neutralAlpha50, }, secondary: { diff --git a/packages/clerk-js/src/ui/primitives/NotificationBadge.tsx b/packages/clerk-js/src/ui/primitives/NotificationBadge.tsx index d43015df94b..a76d3d56dbb 100644 --- a/packages/clerk-js/src/ui/primitives/NotificationBadge.tsx +++ b/packages/clerk-js/src/ui/primitives/NotificationBadge.tsx @@ -21,7 +21,7 @@ const { applyVariants, filterProps } = createVariants(theme => ({ textVariant: { ...common.textVariants(theme) }, colorScheme: { primary: { - [vars.accent]: theme.colors.$colorTextOnPrimaryBackground, + [vars.accent]: theme.colors.$colorPrimaryForeground, [vars.bg]: `linear-gradient(180deg, ${theme.colors.$whiteAlpha300} 0%, ${theme.colors.$transparent} 100%), ${theme.colors.$primary500}`, borderWidth: 0, }, diff --git a/packages/clerk-js/src/ui/primitives/Text.tsx b/packages/clerk-js/src/ui/primitives/Text.tsx index d81f3548477..f187d73c07d 100644 --- a/packages/clerk-js/src/ui/primitives/Text.tsx +++ b/packages/clerk-js/src/ui/primitives/Text.tsx @@ -16,7 +16,7 @@ const { applyVariants, filterProps } = createVariants(theme => { variant: common.textVariants(theme), colorScheme: { body: { color: theme.colors.$colorText }, - onPrimaryBg: { color: theme.colors.$colorTextOnPrimaryBackground }, + onPrimaryBg: { color: theme.colors.$colorPrimaryForeground }, danger: { color: theme.colors.$danger500 }, success: { color: theme.colors.$success500 }, warning: { color: theme.colors.$warning500 }, diff --git a/packages/themes/src/themes/dark.ts b/packages/themes/src/themes/dark.ts index 59f1f1cb7c2..5f058e8b5c4 100644 --- a/packages/themes/src/themes/dark.ts +++ b/packages/themes/src/themes/dark.ts @@ -5,7 +5,7 @@ export const dark = experimental_createTheme({ colorBackground: '#212126', colorNeutral: 'white', colorPrimary: '#ffffff', - colorTextOnPrimaryBackground: 'black', + colorPrimaryForeground: 'black', colorText: 'white', colorInputText: 'white', colorInputBackground: '#26262B', diff --git a/packages/themes/src/themes/shadesOfPurple.ts b/packages/themes/src/themes/shadesOfPurple.ts index 7099a2639e8..9fea72a3ca0 100644 --- a/packages/themes/src/themes/shadesOfPurple.ts +++ b/packages/themes/src/themes/shadesOfPurple.ts @@ -6,7 +6,7 @@ export const shadesOfPurple = experimental_createTheme({ variables: { colorBackground: '#3f3c77', colorPrimary: '#f8d80d', - colorTextOnPrimaryBackground: '#38375f', + colorPrimaryForeground: '#38375f', colorInputText: '#a1fdfe', colorShimmer: 'rgba(161,253,254,0.36)', }, diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index a4e427dfd3b..0e401e0dd42 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -624,9 +624,16 @@ export type Variables = { /** * The color of text appearing on top of an element that with a background color of {@link Variables.colorPrimary}, * eg: solid primary buttons. + * @deprecated Use {@link Variables.colorPrimaryForeground} instead. * @default 'white' */ colorTextOnPrimaryBackground?: CssColor; + /** + * The color of text appearing on top of an element that with a background color of {@link Variables.colorPrimary}, + * eg: solid primary buttons. + * @default 'white' + */ + colorPrimaryForeground?: CssColor; /** * The color used to indicate errors or destructive actions. Set this to your brand's danger color. * @default '#EF4444' From a649d3c5946994f5a799ca1c3f19d3ac6febfdc3 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Thu, 10 Jul 2025 15:42:04 -0400 Subject: [PATCH 02/14] spacingUnit -> spacing --- .../ui/customizables/__tests__/parseAppearance.test.tsx | 4 ++-- packages/clerk-js/src/ui/customizables/parseVariables.ts | 7 ++++--- packages/clerk-js/src/ui/foundations/sizes.ts | 2 +- packages/types/src/appearance.ts | 6 ++++++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx b/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx index ccda943c167..cade0a25d10 100644 --- a/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx +++ b/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx @@ -25,7 +25,7 @@ const themeA = { fontFamilyButtons: 'Comic Sans', fontSize: '1rem', fontWeight: { normal: 600 }, - spacingUnit: 'px', + spacing: 'px', }, } as const; @@ -47,7 +47,7 @@ const themeB = { fontFamilyButtons: 'Arial', fontSize: '2rem', fontWeight: { normal: 700 }, - spacingUnit: 'px', + spacing: 'px', }, } as const; diff --git a/packages/clerk-js/src/ui/customizables/parseVariables.ts b/packages/clerk-js/src/ui/customizables/parseVariables.ts index 89c39085f83..35bcd357ce0 100644 --- a/packages/clerk-js/src/ui/customizables/parseVariables.ts +++ b/packages/clerk-js/src/ui/customizables/parseVariables.ts @@ -107,15 +107,16 @@ export const createRadiiUnits = (theme: Theme) => { }; export const createSpaceScale = (theme: Theme) => { - const { spacingUnit } = theme.variables || {}; - if (spacingUnit === undefined) { + const { spacing, spacingUnit } = theme.variables || {}; + const spacingValue = spacing ?? spacingUnit; + if (spacingValue === undefined) { return; } return fromEntries( spaceScaleKeys.map(k => { const num = Number.parseFloat(k.replace('x', '.')); const percentage = (num / 0.5) * 0.125; - return [k, `calc(${spacingUnit} * ${percentage})`]; + return [k, `calc(${spacingValue} * ${percentage})`]; }), ); }; diff --git a/packages/clerk-js/src/ui/foundations/sizes.ts b/packages/clerk-js/src/ui/foundations/sizes.ts index 374bac79c9b..c63cc67bb76 100644 --- a/packages/clerk-js/src/ui/foundations/sizes.ts +++ b/packages/clerk-js/src/ui/foundations/sizes.ts @@ -6,7 +6,7 @@ const baseSpaceUnits = Object.freeze({ px: '1px', } as const); -const dynamicSpaceUnitsDefaultVar = clerkCssVar('spacing-unit', '1rem'); +const dynamicSpaceUnitsDefaultVar = clerkCssVar('spacing', '1rem'); const calcDynamicSpaceUnits = (num: number) => `calc(${dynamicSpaceUnitsDefaultVar} * ((${num} / 0.5) * 0.125))`; const dynamicSpaceUnits = Object.freeze({ diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index 0e401e0dd42..4334d9a3b68 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -724,9 +724,15 @@ export type Variables = { borderRadius?: CssLengthUnit; /** * The base spacing unit that all margins, paddings and gaps between the elements are derived from. + * @deprecated Use {@link Variables.spacing} instead. * @default '1rem' */ spacingUnit?: CssLengthUnit; + /** + * The base spacing that all margins, paddings and gaps between the elements are derived from. + * @default '1rem' + */ + spacing?: CssLengthUnit; }; export type BaseThemeTaggedType = { __type: 'prebuilt_appearance' }; From 405c2609694640631e2fa55fc5b29d96c8c43d3c Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Thu, 10 Jul 2025 17:04:00 -0400 Subject: [PATCH 03/14] fix sizes generation --- packages/clerk-js/src/ui/foundations/sizes.ts | 224 +++++++++++++----- 1 file changed, 163 insertions(+), 61 deletions(-) diff --git a/packages/clerk-js/src/ui/foundations/sizes.ts b/packages/clerk-js/src/ui/foundations/sizes.ts index c63cc67bb76..55b8e559ea0 100644 --- a/packages/clerk-js/src/ui/foundations/sizes.ts +++ b/packages/clerk-js/src/ui/foundations/sizes.ts @@ -1,90 +1,192 @@ import { clerkCssVar } from '../utils/cssVariables'; +const SPACING_BASE_UNIT = '1rem'; +const SPACING_MULTIPLIER = 0.25; // ((num / 0.5) * 0.125) +const BORDER_RADIUS_DEFAULT = '0.375rem'; + const baseSpaceUnits = Object.freeze({ none: '0', xxs: '0.5px', px: '1px', } as const); -const dynamicSpaceUnitsDefaultVar = clerkCssVar('spacing', '1rem'); -const calcDynamicSpaceUnits = (num: number) => `calc(${dynamicSpaceUnitsDefaultVar} * ((${num} / 0.5) * 0.125))`; - -const dynamicSpaceUnits = Object.freeze({ - '0x25': calcDynamicSpaceUnits(0.25), // 0.0625rem - '0x5': calcDynamicSpaceUnits(0.5), // 0.125rem - '1': calcDynamicSpaceUnits(1), // 0.25rem - '1x5': calcDynamicSpaceUnits(1.5), // 0.375rem - '2': calcDynamicSpaceUnits(2), // 0.5rem - '2x5': calcDynamicSpaceUnits(2.5), // 0.625rem - '3': calcDynamicSpaceUnits(3), // 0.75rem - '3x25': calcDynamicSpaceUnits(3.25), // 0.8125rem - '3x5': calcDynamicSpaceUnits(3.5), // 0.875rem - '4': dynamicSpaceUnitsDefaultVar, // 1rem - '4x25': calcDynamicSpaceUnits(4.5), // 1.0625rem - '5': calcDynamicSpaceUnits(5), // 1.25rem - '5x5': calcDynamicSpaceUnits(5.5), // 1.375rem - '6': calcDynamicSpaceUnits(6), // 1.5rem - '7': calcDynamicSpaceUnits(7), // 1.75rem - '7x5': calcDynamicSpaceUnits(7.5), // 1.875rem - '8': calcDynamicSpaceUnits(8), // 2rem - '8x5': calcDynamicSpaceUnits(8.5), // 2.125rem - '8x75': calcDynamicSpaceUnits(8.75), // 2.1875rem - '9': calcDynamicSpaceUnits(9), // 2.25rem - '10': calcDynamicSpaceUnits(10), // 2.5rem - '12': calcDynamicSpaceUnits(12), // 3rem - '13': calcDynamicSpaceUnits(13), // 3.5rem - '16': calcDynamicSpaceUnits(16), // 4rem - '17': calcDynamicSpaceUnits(17), // 4.25rem - '20': calcDynamicSpaceUnits(20), // 5rem - '24': calcDynamicSpaceUnits(24), // 6rem - '28': calcDynamicSpaceUnits(28), // 7rem - '32': calcDynamicSpaceUnits(32), // 8rem - '36': calcDynamicSpaceUnits(36), // 9rem - '40': calcDynamicSpaceUnits(40), // 10rem - '44': calcDynamicSpaceUnits(44), // 11rem - '48': calcDynamicSpaceUnits(48), // 12rem - '52': calcDynamicSpaceUnits(52), // 13rem - '56': calcDynamicSpaceUnits(56), // 14rem - '57': calcDynamicSpaceUnits(57), // 14.25rem - '60': calcDynamicSpaceUnits(60), // 15rem - '66': calcDynamicSpaceUnits(66), // 16.5rem - '94': calcDynamicSpaceUnits(94), // 23.5rem - '100': calcDynamicSpaceUnits(100), // 25rem - '108': calcDynamicSpaceUnits(108), // 27rem - '120': calcDynamicSpaceUnits(120), // 30rem - '140': calcDynamicSpaceUnits(140), // 35rem - '160': calcDynamicSpaceUnits(160), // 40rem - '176': calcDynamicSpaceUnits(176), // 44rem - '220': calcDynamicSpaceUnits(220), // 55rem +/** + * Spacing scale configuration + * Maps scale keys to their rem values and multipliers for dynamic calculation + */ +const spacingScale = Object.freeze({ + '0x25': { rem: '0.0625rem', multiplier: 0.25 }, + '0x5': { rem: '0.125rem', multiplier: 0.5 }, + '1': { rem: '0.25rem', multiplier: 1 }, + '1x5': { rem: '0.375rem', multiplier: 1.5 }, + '2': { rem: '0.5rem', multiplier: 2 }, + '2x5': { rem: '0.625rem', multiplier: 2.5 }, + '3': { rem: '0.75rem', multiplier: 3 }, + '3x25': { rem: '0.8125rem', multiplier: 3.25 }, + '3x5': { rem: '0.875rem', multiplier: 3.5 }, + '4': { rem: '1rem', multiplier: 4 }, + '4x25': { rem: '1.0625rem', multiplier: 4.25 }, + '5': { rem: '1.25rem', multiplier: 5 }, + '5x5': { rem: '1.375rem', multiplier: 5.5 }, + '6': { rem: '1.5rem', multiplier: 6 }, + '7': { rem: '1.75rem', multiplier: 7 }, + '7x5': { rem: '1.875rem', multiplier: 7.5 }, + '8': { rem: '2rem', multiplier: 8 }, + '8x5': { rem: '2.125rem', multiplier: 8.5 }, + '8x75': { rem: '2.1875rem', multiplier: 8.75 }, + '9': { rem: '2.25rem', multiplier: 9 }, + '10': { rem: '2.5rem', multiplier: 10 }, + '12': { rem: '3rem', multiplier: 12 }, + '13': { rem: '3.5rem', multiplier: 13 }, + '16': { rem: '4rem', multiplier: 16 }, + '17': { rem: '4.25rem', multiplier: 17 }, + '20': { rem: '5rem', multiplier: 20 }, + '24': { rem: '6rem', multiplier: 24 }, + '28': { rem: '7rem', multiplier: 28 }, + '32': { rem: '8rem', multiplier: 32 }, + '36': { rem: '9rem', multiplier: 36 }, + '40': { rem: '10rem', multiplier: 40 }, + '44': { rem: '11rem', multiplier: 44 }, + '48': { rem: '12rem', multiplier: 48 }, + '52': { rem: '13rem', multiplier: 52 }, + '56': { rem: '14rem', multiplier: 56 }, + '57': { rem: '14.25rem', multiplier: 57 }, + '60': { rem: '15rem', multiplier: 60 }, + '66': { rem: '16.5rem', multiplier: 66 }, + '94': { rem: '23.5rem', multiplier: 94 }, + '100': { rem: '25rem', multiplier: 100 }, + '108': { rem: '27rem', multiplier: 108 }, + '120': { rem: '30rem', multiplier: 120 }, + '140': { rem: '35rem', multiplier: 140 }, + '160': { rem: '40rem', multiplier: 160 }, + '176': { rem: '44rem', multiplier: 176 }, + '220': { rem: '55rem', multiplier: 220 }, } as const); +type SpacingScaleKey = keyof typeof spacingScale; + +const dynamicSpaceUnitsDefaultVar = clerkCssVar('spacing', SPACING_BASE_UNIT); + /** - * Instead of generating these values with the helpers of parseVariables, - * we hard code them in order to have better intellisense support while developing + * Calculates a dynamic spacing unit based on the CSS variable + * @param multiplier - The multiplier to apply to the base spacing unit + * @returns CSS calc() expression for dynamic spacing + */ +const calcDynamicSpaceUnits = (multiplier: number): string => { + // Special case for the base unit (4 = 1rem) + if (multiplier === 4) { + return dynamicSpaceUnitsDefaultVar; + } + return `calc(${dynamicSpaceUnitsDefaultVar} * ${multiplier * SPACING_MULTIPLIER})`; +}; + +/** + * Type helper to extract rem values while preserving literal types + */ +type ExtractRemValues = { + readonly [K in keyof T]: T[K] extends { rem: infer R } ? R : never; +}; + +/** + * Generate static spacing units from the spacing scale + * Uses mapped types to preserve literal string types for better intellisense + */ +const spaceUnits = Object.freeze({ + '0x25': spacingScale['0x25'].rem, + '0x5': spacingScale['0x5'].rem, + '1': spacingScale['1'].rem, + '1x5': spacingScale['1x5'].rem, + '2': spacingScale['2'].rem, + '2x5': spacingScale['2x5'].rem, + '3': spacingScale['3'].rem, + '3x25': spacingScale['3x25'].rem, + '3x5': spacingScale['3x5'].rem, + '4': spacingScale['4'].rem, + '4x25': spacingScale['4x25'].rem, + '5': spacingScale['5'].rem, + '5x5': spacingScale['5x5'].rem, + '6': spacingScale['6'].rem, + '7': spacingScale['7'].rem, + '7x5': spacingScale['7x5'].rem, + '8': spacingScale['8'].rem, + '8x5': spacingScale['8x5'].rem, + '8x75': spacingScale['8x75'].rem, + '9': spacingScale['9'].rem, + '10': spacingScale['10'].rem, + '12': spacingScale['12'].rem, + '13': spacingScale['13'].rem, + '16': spacingScale['16'].rem, + '17': spacingScale['17'].rem, + '20': spacingScale['20'].rem, + '24': spacingScale['24'].rem, + '28': spacingScale['28'].rem, + '32': spacingScale['32'].rem, + '36': spacingScale['36'].rem, + '40': spacingScale['40'].rem, + '44': spacingScale['44'].rem, + '48': spacingScale['48'].rem, + '52': spacingScale['52'].rem, + '56': spacingScale['56'].rem, + '57': spacingScale['57'].rem, + '60': spacingScale['60'].rem, + '66': spacingScale['66'].rem, + '94': spacingScale['94'].rem, + '100': spacingScale['100'].rem, + '108': spacingScale['108'].rem, + '120': spacingScale['120'].rem, + '140': spacingScale['140'].rem, + '160': spacingScale['160'].rem, + '176': spacingScale['176'].rem, + '220': spacingScale['220'].rem, +} as const) satisfies ExtractRemValues; + +/** + * Generate dynamic spacing units from the spacing scale + */ +const dynamicSpaceUnits = Object.freeze( + Object.fromEntries( + Object.entries(spacingScale).map(([key, { multiplier }]) => [key, calcDynamicSpaceUnits(multiplier)]), + ), +) as Record; + +/** + * Complete spacing scale combining base units and dynamic spacing + * Used for responsive spacing that adapts to the CSS variable */ const space = Object.freeze({ ...baseSpaceUnits, ...dynamicSpaceUnits, } as const); -const sizes = Object.freeze({ ...space } as const); +/** + * Static sizes combining base units and fixed spacing values + * Used for non-responsive sizing + */ +const sizes = Object.freeze({ + ...baseSpaceUnits, + ...spaceUnits, +} as const); + +const radiiDefaultVar = clerkCssVar('border-radius', BORDER_RADIUS_DEFAULT); -const radiiDefaultVar = clerkCssVar('border-radius', '0.375rem'); +/** + * Border radius scale with CSS variables for theming + */ const radii = Object.freeze({ none: '0px', circle: '50%', - avatar: clerkCssVar('radius-avatar', radiiDefaultVar), // 0.375rem - sm: clerkCssVar('radius-sm', `calc(${radiiDefaultVar} * 0.666)`), // 0.25rem - md: clerkCssVar('radius-md', radiiDefaultVar), // 0.375rem - lg: clerkCssVar('radius-lg', `calc(${radiiDefaultVar} * 1.333)`), // 0.5rem - xl: clerkCssVar('radius-xl', `calc(${radiiDefaultVar} * 2)`), // 0.75rem + avatar: clerkCssVar('radius-avatar', radiiDefaultVar), + sm: clerkCssVar('radius-sm', `calc(${radiiDefaultVar} * 0.666)`), + md: clerkCssVar('radius-md', radiiDefaultVar), + lg: clerkCssVar('radius-lg', `calc(${radiiDefaultVar} * 1.333)`), + xl: clerkCssVar('radius-xl', `calc(${radiiDefaultVar} * 2)`), halfHeight: '99999px', } as const); /** * Used by the space scale generation helpers. - * These keys should always match {@link space} + * These keys should always match the spacing scale */ -const spaceScaleKeys = Object.keys(dynamicSpaceUnits) as Array; +const spaceScaleKeys = Object.keys(spacingScale) as SpacingScaleKey[]; export { sizes, space, radii, spaceScaleKeys }; From 6705a652fd810ca57a4efad2b1da4cb685a8ddc0 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Fri, 11 Jul 2025 09:15:42 -0400 Subject: [PATCH 04/14] colorTextSecondary -> colorMutedForeground --- .../src/ui/components/ApiKeys/ApiKeysTable.tsx | 2 +- .../CreateOrganization/CreateOrganizationForm.tsx | 2 +- .../src/ui/components/OAuthConsent/OAuthConsent.tsx | 4 ++-- .../OrganizationMembersTabInvitations.tsx | 2 +- .../OrganizationMembersTabRequests.tsx | 2 +- .../OrganizationSwitcherTrigger.tsx | 2 +- .../UserInvitationSuggestionList.tsx | 8 ++++---- .../components/PaymentAttempts/PaymentAttemptPage.tsx | 2 +- .../ui/components/PaymentSources/AddPaymentSource.tsx | 2 +- .../ui/components/PaymentSources/PaymentSourceRow.tsx | 2 +- .../src/ui/components/Statements/Statement.tsx | 4 ++-- .../ui/components/Subscriptions/SubscriptionsList.tsx | 2 +- .../customizables/__tests__/parseAppearance.test.tsx | 6 +++--- .../clerk-js/src/ui/customizables/parseVariables.ts | 7 +++++-- .../src/ui/elements/Card/CardClerkAndPagesTag.tsx | 2 +- packages/clerk-js/src/ui/elements/Card/CardContent.tsx | 2 +- packages/clerk-js/src/ui/elements/Drawer.tsx | 2 +- packages/clerk-js/src/ui/elements/InformationBox.tsx | 2 +- packages/clerk-js/src/ui/elements/LineItems.tsx | 10 +++++----- packages/clerk-js/src/ui/elements/PreviewButton.tsx | 2 +- .../src/ui/elements/ProfileCard/ProfileCardRoot.tsx | 2 +- packages/clerk-js/src/ui/elements/SegmentedControl.tsx | 2 +- packages/clerk-js/src/ui/elements/TagInput.tsx | 4 ++-- packages/clerk-js/src/ui/foundations/colors.ts | 6 +++--- packages/clerk-js/src/ui/primitives/AlertIcon.tsx | 2 +- packages/clerk-js/src/ui/primitives/Input.tsx | 2 +- packages/clerk-js/src/ui/primitives/Link.tsx | 2 +- packages/clerk-js/src/ui/primitives/Text.tsx | 2 +- packages/types/src/appearance.ts | 7 +++++++ 29 files changed, 53 insertions(+), 43 deletions(-) diff --git a/packages/clerk-js/src/ui/components/ApiKeys/ApiKeysTable.tsx b/packages/clerk-js/src/ui/components/ApiKeys/ApiKeysTable.tsx index fc6917bc9f7..f1d9f080e49 100644 --- a/packages/clerk-js/src/ui/components/ApiKeys/ApiKeysTable.tsx +++ b/packages/clerk-js/src/ui/components/ApiKeys/ApiKeysTable.tsx @@ -99,7 +99,7 @@ const SecretInputWithToggle = ({ apiKeyID }: { apiKeyID: string }) => { > ({ color: t.colors.$colorTextSecondary })} + sx={t => ({ color: t.colors.$colorMutedForeground })} /> diff --git a/packages/clerk-js/src/ui/components/CreateOrganization/CreateOrganizationForm.tsx b/packages/clerk-js/src/ui/components/CreateOrganization/CreateOrganizationForm.tsx index bde621e62ac..e85e459e987 100644 --- a/packages/clerk-js/src/ui/components/CreateOrganization/CreateOrganizationForm.tsx +++ b/packages/clerk-js/src/ui/components/CreateOrganization/CreateOrganizationForm.tsx @@ -162,7 +162,7 @@ export const CreateOrganizationForm = withCardStateProvider((props: CreateOrgani size='md' icon={Upload} sx={t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, transitionDuration: t.transitionDuration.$controls, })} /> diff --git a/packages/clerk-js/src/ui/components/OAuthConsent/OAuthConsent.tsx b/packages/clerk-js/src/ui/components/OAuthConsent/OAuthConsent.tsx index 1db5f4580c0..a453a1d223a 100644 --- a/packages/clerk-js/src/ui/components/OAuthConsent/OAuthConsent.tsx +++ b/packages/clerk-js/src/ui/components/OAuthConsent/OAuthConsent.tsx @@ -152,7 +152,7 @@ export function OAuthConsentInternal() { display: 'inline-block', width: t.space.$1, height: t.space.$1, - background: t.colors.$colorTextSecondary, + background: t.colors.$colorMutedForeground, borderRadius: t.radii.$circle, transform: 'translateY(-0.1875rem)', marginRight: t.space.$2, @@ -369,7 +369,7 @@ function ConnectionSeparator() { height={2} aria-hidden sx={t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, })} > { )} sx={t => ({ paddingLeft: t.space.$10, - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, [mqu.md]: { paddingLeft: 0, }, diff --git a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationMembersTabRequests.tsx b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationMembersTabRequests.tsx index 02bf9752110..4392b97460f 100644 --- a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationMembersTabRequests.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationMembersTabRequests.tsx @@ -72,7 +72,7 @@ export const OrganizationMembersTabRequests = () => { )} sx={t => ({ paddingLeft: t.space.$10, - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, [mqu.md]: { paddingLeft: 0, }, diff --git a/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherTrigger.tsx b/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherTrigger.tsx index 1c09ebe39e0..5ed37744642 100644 --- a/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherTrigger.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherTrigger.tsx @@ -67,7 +67,7 @@ export const OrganizationSwitcherTrigger = withAvatarShimmer( gap={3} user={userWithoutIdentifiers} showAvatar={!hidePersonal} - sx={t => ({ color: t.colors.$colorTextSecondary })} + sx={t => ({ color: t.colors.$colorMutedForeground })} title={ hidePersonal ? localizationKeys('organizationSwitcher.notSelected') diff --git a/packages/clerk-js/src/ui/components/OrganizationSwitcher/UserInvitationSuggestionList.tsx b/packages/clerk-js/src/ui/components/OrganizationSwitcher/UserInvitationSuggestionList.tsx index a6fa3e0f2b7..171866d20ca 100644 --- a/packages/clerk-js/src/ui/components/OrganizationSwitcher/UserInvitationSuggestionList.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationSwitcher/UserInvitationSuggestionList.tsx @@ -120,9 +120,9 @@ const Preview = ( elementId='organizationSwitcherListedOrganization' organization={publicOrganizationData} sx={t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, ':hover': { - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, }, })} /> @@ -186,9 +186,9 @@ const InvitationPreview = withCardStateProvider( elementId='organizationSwitcherListedOrganization' organization={publicOrganizationData} sx={t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, ':hover': { - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, }, })} /> diff --git a/packages/clerk-js/src/ui/components/PaymentAttempts/PaymentAttemptPage.tsx b/packages/clerk-js/src/ui/components/PaymentAttempts/PaymentAttemptPage.tsx index 16e99a1343b..9e853d65eb1 100644 --- a/packages/clerk-js/src/ui/components/PaymentAttempts/PaymentAttemptPage.tsx +++ b/packages/clerk-js/src/ui/components/PaymentAttempts/PaymentAttemptPage.tsx @@ -102,7 +102,7 @@ export const PaymentAttemptPage = () => { display: 'flex', alignItems: 'center', gap: t.space.$0x25, - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, })} > { colorPrimary: resolveComputedCSSColor(node, colors.$primary500, colors.$colorBackground), colorBackground: resolveComputedCSSColor(node, colors.$colorInputBackground, colors.$colorBackground), colorText: resolveComputedCSSColor(node, colors.$colorText, colors.$colorBackground), - colorTextSecondary: resolveComputedCSSColor(node, colors.$colorTextSecondary, colors.$colorBackground), + colorTextSecondary: resolveComputedCSSColor(node, colors.$colorMutedForeground, colors.$colorBackground), colorSuccess: resolveComputedCSSColor(node, colors.$success500, colors.$colorBackground), colorDanger: resolveComputedCSSColor(node, colors.$danger500, colors.$colorBackground), colorWarning: resolveComputedCSSColor(node, colors.$warning500, colors.$colorBackground), diff --git a/packages/clerk-js/src/ui/components/PaymentSources/PaymentSourceRow.tsx b/packages/clerk-js/src/ui/components/PaymentSources/PaymentSourceRow.tsx index 19a6a7f0f93..c5312270f50 100644 --- a/packages/clerk-js/src/ui/components/PaymentSources/PaymentSourceRow.tsx +++ b/packages/clerk-js/src/ui/components/PaymentSources/PaymentSourceRow.tsx @@ -24,7 +24,7 @@ export const PaymentSourceRow = ({ paymentSource }: { paymentSource: CommercePay {paymentSource.paymentMethod === 'card' ? paymentSource.cardType : paymentSource.paymentMethod} ({ color: t.colors.$colorTextSecondary })} + sx={t => ({ color: t.colors.$colorMutedForeground })} variant='caption' truncate elementDescriptor={descriptors.paymentSourceRowValue} diff --git a/packages/clerk-js/src/ui/components/Statements/Statement.tsx b/packages/clerk-js/src/ui/components/Statements/Statement.tsx index 1192e5328ab..52a91601b5f 100644 --- a/packages/clerk-js/src/ui/components/Statements/Statement.tsx +++ b/packages/clerk-js/src/ui/components/Statements/Statement.tsx @@ -54,7 +54,7 @@ function Header({ title, id, status }: { title: string | LocalizationKey; id: st display: 'flex', alignItems: 'center', gap: t.space.$0x25, - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, })} > {typeof value === 'string' ? ( diff --git a/packages/clerk-js/src/ui/components/Subscriptions/SubscriptionsList.tsx b/packages/clerk-js/src/ui/components/Subscriptions/SubscriptionsList.tsx index 9c08b9f1258..2a05dc36eb4 100644 --- a/packages/clerk-js/src/ui/components/Subscriptions/SubscriptionsList.tsx +++ b/packages/clerk-js/src/ui/components/Subscriptions/SubscriptionsList.tsx @@ -158,7 +158,7 @@ export function SubscriptionsList({ {(subscription.plan.amount > 0 || subscription.plan.annualAmount > 0) && ( ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, textTransform: 'lowercase', ':before': { content: '"/"', diff --git a/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx b/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx index cade0a25d10..2236ee7f133 100644 --- a/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx +++ b/packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx @@ -83,7 +83,7 @@ describe('AppearanceProvider internalTheme flows', () => { expect(result.current.parsedInternalTheme.colors.$colorInputText).toBe(knownColors[themeAColor]); expect(result.current.parsedInternalTheme.colors.$colorText).toBe(knownColors[themeAColor]); expect(result.current.parsedInternalTheme.colors.$colorPrimaryForeground).toBe(knownColors[themeAColor]); - expect(result.current.parsedInternalTheme.colors.$colorTextSecondary).toBe(knownColors[themeAColor]); + expect(result.current.parsedInternalTheme.colors.$colorMutedForeground).toBe(knownColors[themeAColor]); expect(result.current.parsedInternalTheme.radii.$md).toBe(themeA.variables.borderRadius); expect(result.current.parsedInternalTheme.fonts.$main).toBe(themeA.variables.fontFamily); expect(result.current.parsedInternalTheme.fonts.$buttons).toBe(themeA.variables.fontFamily); @@ -113,7 +113,7 @@ describe('AppearanceProvider internalTheme flows', () => { expect(result.current.parsedInternalTheme.colors.$colorInputText).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorText).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorPrimaryForeground).toBe(knownColors[themeBColor]); - expect(result.current.parsedInternalTheme.colors.$colorTextSecondary).toBe(knownColors[themeBColor]); + expect(result.current.parsedInternalTheme.colors.$colorMutedForeground).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.radii.$md).toBe(themeB.variables.borderRadius); expect(result.current.parsedInternalTheme.fonts.$main).toBe(themeB.variables.fontFamily); expect(result.current.parsedInternalTheme.fonts.$buttons).toBe(themeB.variables.fontFamily); @@ -144,7 +144,7 @@ describe('AppearanceProvider internalTheme flows', () => { expect(result.current.parsedInternalTheme.colors.$colorInputText).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorText).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.colors.$colorPrimaryForeground).toBe(knownColors[themeBColor]); - expect(result.current.parsedInternalTheme.colors.$colorTextSecondary).toBe(knownColors[themeBColor]); + expect(result.current.parsedInternalTheme.colors.$colorMutedForeground).toBe(knownColors[themeBColor]); expect(result.current.parsedInternalTheme.radii.$md).toBe(themeB.variables.borderRadius); expect(result.current.parsedInternalTheme.fonts.$main).toBe(themeB.variables.fontFamily); expect(result.current.parsedInternalTheme.fonts.$buttons).toBe(themeB.variables.fontFamily); diff --git a/packages/clerk-js/src/ui/customizables/parseVariables.ts b/packages/clerk-js/src/ui/customizables/parseVariables.ts index 35bcd357ce0..ed75d2d66cd 100644 --- a/packages/clerk-js/src/ui/customizables/parseVariables.ts +++ b/packages/clerk-js/src/ui/customizables/parseVariables.ts @@ -39,8 +39,11 @@ export const createColorScales = (theme: Theme) => { ? colors.toHslaString(variables.colorTextOnPrimaryBackground) : undefined, colorText: colors.toHslaString(variables.colorText), - colorTextSecondary: - colors.toHslaString(variables.colorTextSecondary) || colors.makeTransparent(variables.colorText, 0.35), + colorMutedForeground: variables.colorMutedForeground + ? colors.toHslaString(variables.colorMutedForeground) + : variables.colorTextSecondary + ? colors.toHslaString(variables.colorTextSecondary) + : colors.makeTransparent(variables.colorText, 0.35), colorInputText: colors.toHslaString(variables.colorInputText), colorBackground: colors.toHslaString(variables.colorBackground), colorInputBackground: colors.toHslaString(variables.colorInputBackground), diff --git a/packages/clerk-js/src/ui/elements/Card/CardClerkAndPagesTag.tsx b/packages/clerk-js/src/ui/elements/Card/CardClerkAndPagesTag.tsx index 9de7fac141a..9008f1d498f 100644 --- a/packages/clerk-js/src/ui/elements/Card/CardClerkAndPagesTag.tsx +++ b/packages/clerk-js/src/ui/elements/Card/CardClerkAndPagesTag.tsx @@ -70,7 +70,7 @@ export const CardClerkAndPagesTag = React.memo( gap={1} align='center' justify='center' - sx={t => ({ color: t.colors.$colorTextSecondary })} + sx={t => ({ color: t.colors.$colorMutedForeground })} > <> Secured by diff --git a/packages/clerk-js/src/ui/elements/Card/CardContent.tsx b/packages/clerk-js/src/ui/elements/Card/CardContent.tsx index f18454620ae..ff409108145 100644 --- a/packages/clerk-js/src/ui/elements/Card/CardContent.tsx +++ b/packages/clerk-js/src/ui/elements/Card/CardContent.tsx @@ -66,7 +66,7 @@ export const CardContent = React.forwardRef((p /> } sx={t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, zIndex: t.zIndices.$modal, position: 'absolute', top: t.space.$2, diff --git a/packages/clerk-js/src/ui/elements/Drawer.tsx b/packages/clerk-js/src/ui/elements/Drawer.tsx index 49622abc644..d0612f4a1a6 100644 --- a/packages/clerk-js/src/ui/elements/Drawer.tsx +++ b/packages/clerk-js/src/ui/elements/Drawer.tsx @@ -419,7 +419,7 @@ const Close = React.forwardRef((_, ref) => { /> } sx={t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, padding: t.space.$3, marginInlineStart: 'auto', })} diff --git a/packages/clerk-js/src/ui/elements/InformationBox.tsx b/packages/clerk-js/src/ui/elements/InformationBox.tsx index db080a53548..81a65e0c905 100644 --- a/packages/clerk-js/src/ui/elements/InformationBox.tsx +++ b/packages/clerk-js/src/ui/elements/InformationBox.tsx @@ -22,7 +22,7 @@ export function InformationBox(props: InformationBoxProps) { /> ({ color: t.colors.$colorTextSecondary })} + sx={t => ({ color: t.colors.$colorMutedForeground })} /> ); diff --git a/packages/clerk-js/src/ui/elements/LineItems.tsx b/packages/clerk-js/src/ui/elements/LineItems.tsx index 461806babf4..04737a16b50 100644 --- a/packages/clerk-js/src/ui/elements/LineItems.tsx +++ b/packages/clerk-js/src/ui/elements/LineItems.tsx @@ -100,7 +100,7 @@ const Title = React.forwardRef(({ title, descr elementId={descriptors.lineItemsTitle.setId(variant)} sx={t => ({ display: 'grid', - color: variant === 'primary' ? t.colors.$colorText : t.colors.$colorTextSecondary, + color: variant === 'primary' ? t.colors.$colorText : t.colors.$colorMutedForeground, ...common.textVariants(t)[textVariant], })} > @@ -126,7 +126,7 @@ const Title = React.forwardRef(({ title, descr elementDescriptor={descriptors.lineItemsTitleDescription} sx={t => ({ fontSize: t.fontSizes.$sm, - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, })} /> ) : null} @@ -172,7 +172,7 @@ function Description({ text, prefix, suffix, truncateText = false, copyText = fa sx={t => ({ display: 'grid', justifyContent: 'end', - color: variant === 'tertiary' ? t.colors.$colorTextSecondary : t.colors.$colorText, + color: variant === 'tertiary' ? t.colors.$colorMutedForeground : t.colors.$colorText, })} > ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, ...common.textVariants(t).caption, })} /> @@ -222,7 +222,7 @@ function Description({ text, prefix, suffix, truncateText = false, copyText = fa localizationKey={suffix} elementDescriptor={descriptors.lineItemsDescriptionSuffix} sx={t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, ...common.textVariants(t).caption, justifySelf: 'flex-end', })} diff --git a/packages/clerk-js/src/ui/elements/PreviewButton.tsx b/packages/clerk-js/src/ui/elements/PreviewButton.tsx index f8d170a3754..06a420ac938 100644 --- a/packages/clerk-js/src/ui/elements/PreviewButton.tsx +++ b/packages/clerk-js/src/ui/elements/PreviewButton.tsx @@ -45,7 +45,7 @@ export const PreviewButton = (props: PreviewButtonProps) => { icon={icon} sx={[ t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, marginLeft: t.space.$2, visibility: showIconOnHover ? 'hidden' : 'initial', }), diff --git a/packages/clerk-js/src/ui/elements/ProfileCard/ProfileCardRoot.tsx b/packages/clerk-js/src/ui/elements/ProfileCard/ProfileCardRoot.tsx index 561c4e0f556..2ff26582860 100644 --- a/packages/clerk-js/src/ui/elements/ProfileCard/ProfileCardRoot.tsx +++ b/packages/clerk-js/src/ui/elements/ProfileCard/ProfileCardRoot.tsx @@ -59,7 +59,7 @@ export const ProfileCardRoot = React.forwardRef } sx={t => ({ - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, padding: t.space.$3, })} /> diff --git a/packages/clerk-js/src/ui/elements/SegmentedControl.tsx b/packages/clerk-js/src/ui/elements/SegmentedControl.tsx index b80cb2054f9..bebb32a3352 100644 --- a/packages/clerk-js/src/ui/elements/SegmentedControl.tsx +++ b/packages/clerk-js/src/ui/elements/SegmentedControl.tsx @@ -136,7 +136,7 @@ const Button = React.forwardRef(({ text, value } position: 'relative', width: fullWidth ? '100%' : 'auto', backgroundColor: isSelected ? t.colors.$colorBackground : 'transparent', - color: isSelected ? t.colors.$colorText : t.colors.$colorTextSecondary, + color: isSelected ? t.colors.$colorText : t.colors.$colorMutedForeground, fontSize: size === 'lg' ? t.fontSizes.$md : t.fontSizes.$xs, minHeight: t.sizes.$6, boxShadow: isSelected ? t.shadows.$segmentedControl : 'none', diff --git a/packages/clerk-js/src/ui/elements/TagInput.tsx b/packages/clerk-js/src/ui/elements/TagInput.tsx index 9623f649c25..f11a6375ffa 100644 --- a/packages/clerk-js/src/ui/elements/TagInput.tsx +++ b/packages/clerk-js/src/ui/elements/TagInput.tsx @@ -165,7 +165,7 @@ export const TagInput = (props: TagInputProps) => { lineHeight: t.space.$5, paddingLeft: t.space.$1, '::placeholder': { - color: t.colors.$colorTextSecondary, + color: t.colors.$colorMutedForeground, }, boxShadow: 'none', ':hover': { @@ -219,7 +219,7 @@ const TagPill = (props: TagPillProps) => { elementDescriptor={descriptors.tagPillIcon} size='md' icon={Plus} - sx={t => ({ color: t.colors.$colorTextSecondary, transform: 'translateY(0px) rotate(45deg)' })} + sx={t => ({ color: t.colors.$colorMutedForeground, transform: 'translateY(0px) rotate(45deg)' })} /> ); diff --git a/packages/clerk-js/src/ui/foundations/colors.ts b/packages/clerk-js/src/ui/foundations/colors.ts index 0138ea65049..b76630607e6 100644 --- a/packages/clerk-js/src/ui/foundations/colors.ts +++ b/packages/clerk-js/src/ui/foundations/colors.ts @@ -72,8 +72,8 @@ const warningAlphaScale = colorOptionToThemedAlphaScale( ) as AlphaScale<'warningAlpha'>; const colorText = clerkCssVar('color-text', '#212126'); -const colorTextSecondary = clerkCssVar( - 'color-text-secondary', +const colorMutedForeground = clerkCssVar( + 'color-muted-foreground', colorUtils.makeTransparent(colorText, 0.35) || '#747686', ); @@ -84,7 +84,7 @@ const colors = Object.freeze({ colorBackground: clerkCssVar('color-background', 'white'), colorInputBackground: clerkCssVar('color-input-background', 'white'), colorText, - colorTextSecondary, + colorMutedForeground, colorInputText: clerkCssVar('color-input-text', '#131316'), colorPrimaryForeground: clerkCssVar('color-primary-foreground', 'white'), colorShimmer: clerkCssVar('color-shimmer', 'rgba(255, 255, 255, 0.36)'), diff --git a/packages/clerk-js/src/ui/primitives/AlertIcon.tsx b/packages/clerk-js/src/ui/primitives/AlertIcon.tsx index 093d63853d9..eb0c9e0ccd3 100644 --- a/packages/clerk-js/src/ui/primitives/AlertIcon.tsx +++ b/packages/clerk-js/src/ui/primitives/AlertIcon.tsx @@ -14,7 +14,7 @@ const { applyVariants, filterProps } = createVariants(theme => ({ warning: { color: theme.colors.$warning500 }, success: { color: theme.colors.$success500 }, primary: { color: theme.colors.$primary500 }, - info: { color: theme.colors.$colorTextSecondary }, + info: { color: theme.colors.$colorMutedForeground }, }, }, })); diff --git a/packages/clerk-js/src/ui/primitives/Input.tsx b/packages/clerk-js/src/ui/primitives/Input.tsx index d40862fc173..dc34a4853d2 100644 --- a/packages/clerk-js/src/ui/primitives/Input.tsx +++ b/packages/clerk-js/src/ui/primitives/Input.tsx @@ -32,7 +32,7 @@ const { applyVariants, filterProps } = createVariants((theme, props) => ({ animationName: 'onAutoFillStart', }, '::placeholder': { - color: theme.colors.$colorTextSecondary, + color: theme.colors.$colorMutedForeground, }, }, variants: { diff --git a/packages/clerk-js/src/ui/primitives/Link.tsx b/packages/clerk-js/src/ui/primitives/Link.tsx index 08ef6d89f95..136ef88fa1a 100644 --- a/packages/clerk-js/src/ui/primitives/Link.tsx +++ b/packages/clerk-js/src/ui/primitives/Link.tsx @@ -29,7 +29,7 @@ const { applyVariants, filterProps } = createVariants(theme => ({ '&:active': { color: theme.colors.$danger600 }, }, neutral: { - color: theme.colors.$colorTextSecondary, + color: theme.colors.$colorMutedForeground, }, inherit: { color: 'inherit' }, }, diff --git a/packages/clerk-js/src/ui/primitives/Text.tsx b/packages/clerk-js/src/ui/primitives/Text.tsx index f187d73c07d..91c7b81b7c0 100644 --- a/packages/clerk-js/src/ui/primitives/Text.tsx +++ b/packages/clerk-js/src/ui/primitives/Text.tsx @@ -20,7 +20,7 @@ const { applyVariants, filterProps } = createVariants(theme => { danger: { color: theme.colors.$danger500 }, success: { color: theme.colors.$success500 }, warning: { color: theme.colors.$warning500 }, - secondary: { color: theme.colors.$colorTextSecondary }, + secondary: { color: theme.colors.$colorMutedForeground }, inherit: { color: 'inherit' }, }, truncate: { diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index 4334d9a3b68..1c94ddb5363 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -664,9 +664,16 @@ export type Variables = { /** * The text color for elements of lower importance, eg: a subtitle text. * This color is a lighter shade of {@link Variables.colorText}. + * @deprecated Use {@link Variables.colorMutedForeground} instead. * @default '#747686' */ colorTextSecondary?: CssColor; + /** + * The text color for elements of lower importance, eg: a subtitle text. + * This color is a lighter shade of {@link Variables.colorText}. + * @default '#747686' + */ + colorMutedForeground?: CssColor; /** * The background color for the card container. * @default 'white' From ceafc12527b24addc3aa5034c0b879e4aaef4613 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Fri, 11 Jul 2025 09:19:37 -0400 Subject: [PATCH 05/14] colorText -> colorForeground --- .../clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx | 2 +- .../src/ui/components/Checkout/CheckoutComplete.tsx | 4 ++-- .../clerk-js/src/ui/components/Checkout/CheckoutForm.tsx | 2 +- .../clerk-js/src/ui/components/OrganizationList/shared.tsx | 4 ++-- .../ui/components/OrganizationProfile/MemberListTable.tsx | 2 +- .../OrganizationProfile/OrganizationBillingPage.tsx | 2 +- .../src/ui/components/PaymentSources/AddPaymentSource.tsx | 2 +- .../src/ui/components/PaymentSources/PaymentSourceRow.tsx | 2 +- .../src/ui/components/UserButton/UserButtonTrigger.tsx | 2 +- .../clerk-js/src/ui/components/UserProfile/AccountPage.tsx | 2 +- .../clerk-js/src/ui/components/UserProfile/BillingPage.tsx | 2 +- .../ui/components/UserProfile/ConnectedAccountsSection.tsx | 2 +- .../src/ui/components/UserProfile/EmailsSection.tsx | 2 +- .../clerk-js/src/ui/components/UserProfile/PhoneSection.tsx | 2 +- .../src/ui/components/UserProfile/UserProfileSection.tsx | 2 +- .../src/ui/components/UserProfile/UsernameSection.tsx | 2 +- .../src/ui/customizables/__tests__/parseAppearance.test.tsx | 6 +++--- packages/clerk-js/src/ui/customizables/parseVariables.ts | 4 +++- packages/clerk-js/src/ui/elements/Avatar.tsx | 2 +- packages/clerk-js/src/ui/elements/Card/CardRoot.tsx | 2 +- packages/clerk-js/src/ui/elements/Disclosure.tsx | 2 +- packages/clerk-js/src/ui/elements/Header.tsx | 2 +- packages/clerk-js/src/ui/elements/LineItems.tsx | 4 ++-- packages/clerk-js/src/ui/elements/Navbar.tsx | 6 +++--- packages/clerk-js/src/ui/elements/Pagination.tsx | 2 +- packages/clerk-js/src/ui/elements/PhoneInput/index.tsx | 2 +- packages/clerk-js/src/ui/elements/RootBox.tsx | 2 +- packages/clerk-js/src/ui/elements/SegmentedControl.tsx | 2 +- packages/clerk-js/src/ui/foundations/colors.ts | 6 +++--- packages/clerk-js/src/ui/primitives/Button.tsx | 2 +- packages/clerk-js/src/ui/primitives/FormLabel.tsx | 2 +- packages/clerk-js/src/ui/primitives/Heading.tsx | 2 +- packages/clerk-js/src/ui/primitives/Td.tsx | 2 +- packages/clerk-js/src/ui/primitives/Text.tsx | 2 +- packages/clerk-js/src/ui/primitives/Th.tsx | 2 +- packages/types/src/appearance.ts | 6 ++++++ 36 files changed, 52 insertions(+), 44 deletions(-) diff --git a/packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx b/packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx index b5453ef0aec..7900c3d5a44 100644 --- a/packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx +++ b/packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx @@ -110,7 +110,7 @@ const ExpirationSelector: React.FC = ({ selectedExpirat ({ paddingBlock: t.space.$1, - color: t.colors.$colorText, + color: t.colors.$colorForeground, })} /> diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx index 6b5dad5fd62..36632bf8ec2 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx @@ -245,7 +245,7 @@ export const CheckoutComplete = () => { borderRadius: t.radii.$circle, backgroundImage: `linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.30) 95.31%)`, boxShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.35), 0px 1px 0px 0px rgba(255, 255, 255, 0.05) inset', - color: canHover ? t.colors.$success500 : t.colors.$colorText, + color: canHover ? t.colors.$success500 : t.colors.$colorForeground, ':before': { content: '""', position: 'absolute', @@ -319,7 +319,7 @@ export const CheckoutComplete = () => { animationDuration: `${transitionDurationValues.slowest}ms`, animationTimingFunction: transitionTiming.bezier, animationFillMode: 'forwards', - color: t.colors.$colorText, + color: t.colors.$colorForeground, '@keyframes slideUp': { '0%': { transform: 'translateY(30px)', diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx index 5e605dcb55c..147fe70b492 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx @@ -383,7 +383,7 @@ const ExistingPaymentSourceForm = withCardStateProvider( ({ paddingBlock: t.space.$1, - color: t.colors.$colorText, + color: t.colors.$colorForeground, })} /> diff --git a/packages/clerk-js/src/ui/components/OrganizationList/shared.tsx b/packages/clerk-js/src/ui/components/OrganizationList/shared.tsx index 693f8b627e6..36bd022c4ba 100644 --- a/packages/clerk-js/src/ui/components/OrganizationList/shared.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationList/shared.tsx @@ -33,9 +33,9 @@ const sharedStyles: ThemableCssProp = t => ({ }); export const sharedMainIdentifierSx: ThemableCssProp = t => ({ - color: t.colors.$colorText, + color: t.colors.$colorForeground, ':hover': { - color: t.colors.$colorText, + color: t.colors.$colorForeground, }, }); diff --git a/packages/clerk-js/src/ui/components/OrganizationProfile/MemberListTable.tsx b/packages/clerk-js/src/ui/components/OrganizationProfile/MemberListTable.tsx index 79a48b8ee25..b6ed9140d68 100644 --- a/packages/clerk-js/src/ui/components/OrganizationProfile/MemberListTable.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationProfile/MemberListTable.tsx @@ -193,7 +193,7 @@ export const RoleSelect = (props: { sx={ triggerSx || (t => ({ - color: t.colors.$colorText, + color: t.colors.$colorForeground, backgroundColor: 'transparent', textWrap: 'nowrap', })) diff --git a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationBillingPage.tsx b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationBillingPage.tsx index 67e3b272fc1..1fcc2d647c1 100644 --- a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationBillingPage.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationBillingPage.tsx @@ -26,7 +26,7 @@ const OrganizationBillingPageInternal = withCardStateProvider(() => { return ( ({ gap: t.space.$8, color: t.colors.$colorText })} + sx={t => ({ gap: t.space.$8, color: t.colors.$colorForeground })} > { return { colorPrimary: resolveComputedCSSColor(node, colors.$primary500, colors.$colorBackground), colorBackground: resolveComputedCSSColor(node, colors.$colorInputBackground, colors.$colorBackground), - colorText: resolveComputedCSSColor(node, colors.$colorText, colors.$colorBackground), + colorText: resolveComputedCSSColor(node, colors.$colorForeground, colors.$colorBackground), colorTextSecondary: resolveComputedCSSColor(node, colors.$colorMutedForeground, colors.$colorBackground), colorSuccess: resolveComputedCSSColor(node, colors.$success500, colors.$colorBackground), colorDanger: resolveComputedCSSColor(node, colors.$danger500, colors.$colorBackground), diff --git a/packages/clerk-js/src/ui/components/PaymentSources/PaymentSourceRow.tsx b/packages/clerk-js/src/ui/components/PaymentSources/PaymentSourceRow.tsx index c5312270f50..5e538d3e4b5 100644 --- a/packages/clerk-js/src/ui/components/PaymentSources/PaymentSourceRow.tsx +++ b/packages/clerk-js/src/ui/components/PaymentSources/PaymentSourceRow.tsx @@ -17,7 +17,7 @@ export const PaymentSourceRow = ({ paymentSource }: { paymentSource: CommercePay elementDescriptor={descriptors.paymentSourceRowIcon} /> ({ color: t.colors.$colorText, textTransform: 'capitalize' })} + sx={t => ({ color: t.colors.$colorForeground, textTransform: 'capitalize' })} truncate elementDescriptor={descriptors.paymentSourceRowType} > diff --git a/packages/clerk-js/src/ui/components/UserButton/UserButtonTrigger.tsx b/packages/clerk-js/src/ui/components/UserButton/UserButtonTrigger.tsx index d91adb8795d..7a99d4bb645 100644 --- a/packages/clerk-js/src/ui/components/UserButton/UserButtonTrigger.tsx +++ b/packages/clerk-js/src/ui/components/UserButton/UserButtonTrigger.tsx @@ -23,7 +23,7 @@ export const UserButtonTrigger = withAvatarShimmer(