From 565e8dee1003e719c6ce420e99cc5421a577488e Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Fri, 11 Jul 2025 16:33:07 -0400 Subject: [PATCH 1/5] feat(clerk-js): Add `colorShadow` variable option --- .../src/ui/customizables/parseAppearance.ts | 4 +- .../src/ui/customizables/parseVariables.ts | 16 ++++++ .../clerk-js/src/ui/foundations/shadows.ts | 50 ++++++++++++------- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/packages/clerk-js/src/ui/customizables/parseAppearance.ts b/packages/clerk-js/src/ui/customizables/parseAppearance.ts index d0ee1606443..be3e2c45b01 100644 --- a/packages/clerk-js/src/ui/customizables/parseAppearance.ts +++ b/packages/clerk-js/src/ui/customizables/parseAppearance.ts @@ -10,6 +10,7 @@ import { createFontSizeScale, createFontWeightScale, createRadiiUnits, + createShadowsUnits, createSpaceScale, } from './parseVariables'; @@ -144,5 +145,6 @@ const createInternalThemeFromVariables = (theme: Theme | undefined): DeepPartial const fontSizes = { ...createFontSizeScale(theme) }; const fontWeights = { ...createFontWeightScale(theme) }; const fonts = { ...createFonts(theme) }; - return createInternalTheme({ colors, radii, space, fontSizes, fontWeights, fonts } as any); + const shadows = { ...createShadowsUnits(theme) }; + return createInternalTheme({ colors, radii, space, fontSizes, fontWeights, fonts, shadows } as any); }; diff --git a/packages/clerk-js/src/ui/customizables/parseVariables.ts b/packages/clerk-js/src/ui/customizables/parseVariables.ts index de32c640b3c..474a8340e27 100644 --- a/packages/clerk-js/src/ui/customizables/parseVariables.ts +++ b/packages/clerk-js/src/ui/customizables/parseVariables.ts @@ -7,6 +7,7 @@ import { colorOptionToThemedAlphaScale, colorOptionToThemedLightnessScale } from import { cssSupports } from '../utils/cssSupports'; import { fromEntries } from '../utils/fromEntries'; import { removeUndefinedProps } from '../utils/removeUndefinedProps'; +import { createShadowSet } from '../foundations/shadows'; export const createColorScales = (theme: Theme) => { const variables = removeInvalidValues(theme.variables || {}); @@ -181,3 +182,18 @@ export const createFonts = (theme: Theme) => { const { fontFamily, fontFamilyButtons } = theme.variables || {}; return removeUndefinedProps({ main: fontFamily, buttons: fontFamilyButtons }); }; + +export const createShadowsUnits = (theme: Theme) => { + const { colorShadow } = theme.variables || {}; + if (!colorShadow) { + return; + } + + const shadowColor = colors.toHslaString(colorShadow); + if (!shadowColor) { + return; + } + + // Use the shared shadow creation function with the custom shadow color + return createShadowSet(shadowColor); +}; diff --git a/packages/clerk-js/src/ui/foundations/shadows.ts b/packages/clerk-js/src/ui/foundations/shadows.ts index 96f46a467c2..09d26581329 100644 --- a/packages/clerk-js/src/ui/foundations/shadows.ts +++ b/packages/clerk-js/src/ui/foundations/shadows.ts @@ -1,18 +1,32 @@ -export const shadows = Object.freeze({ - menuShadow: '0px 5px 15px 0px rgba(0, 0, 0, 0.08), 0px 15px 35px -5px rgba(25, 28, 33, 0.20)', - fabShadow: '0px 12px 24px rgba(0, 0, 0, 0.32)', - buttonShadow: - '0px 1px 1px 0px rgba(255, 255, 255, 0.07) inset, 0px 2px 3px 0px rgba(34, 42, 53, 0.20), 0px 1px 1px 0px rgba(0, 0, 0, 0.24)', - cardBoxShadow: '0px 5px 15px 0px rgba(0, 0, 0, 0.08), 0px 15px 35px -5px rgba(25, 28, 33, 0.20)', - cardContentShadow: '0px 0px 2px 0px rgba(0, 0, 0, 0.08), 0px 1px 2px 0px rgba(25, 28, 33, 0.06)', - actionCardShadow: '0px 1px 4px 0px rgba(0, 0, 0, 0.12), 0px 4px 8px 0px rgba(106, 115, 133, 0.12)', - outlineButtonShadow: '0px 2px 3px -1px rgba(0, 0, 0, 0.08), 0px 1px 0px 0px rgba(0, 0, 0, 0.02)', - input: '0px 0px 1px 0px {{color}}', - focusRing: '0px 0px 0px 4px {{color}}', - badge: '0px 2px 0px -1px rgba(0, 0, 0, 0.04)', - tableBodyShadow: - '0px 0px 2px 0px rgba(0, 0, 0, 0.08), 0px 1px 2px 0px rgba(25, 28, 33, 0.12), 0px 0px 0px 1px rgba(0, 0, 0, 0.06)', - segmentedControl: '0px 1px 2px 0px rgba(0, 0, 0, 0.08)', - switchControl: - '0px 2px 2px -1px rgba(0, 0, 0, 0.06), 0px 0px 0px 1px rgba(0, 0, 0, 0.06), 0px 4px 4px -2px rgba(0, 0, 0, 0.06)', -} as const); +import { createAlphaColorMixString } from '../utils/colors/utils'; +import { clerkCssVar } from '../utils/cssVariables'; + +const shadow = (color: string, alpha: number) => + clerkCssVar('color-shadow', createAlphaColorMixString(color, alpha * 100)); + +/** + * Creates a complete set of shadows using the provided shadow color + * @param shadowColor - The base color to use for shadows (defaults to black) + * @param highlightColor - The color to use for inset highlights (defaults to white) + * @returns Object containing all shadow definitions + */ +export const createShadowSet = (shadowColor: string = '#000000', highlightColor: string = '#FFFFFF') => { + return { + menuShadow: `0px 5px 15px 0px ${shadow(shadowColor, 0.08)}, 0px 15px 35px -5px ${shadow(shadowColor, 0.2)}`, + fabShadow: `0px 12px 24px ${shadow(shadowColor, 0.32)}`, + buttonShadow: `0px 1px 1px 0px ${shadow(highlightColor, 0.07)} inset, 0px 2px 3px 0px ${shadow(shadowColor, 0.2)}, 0px 1px 1px 0px ${shadow(shadowColor, 0.24)}`, + cardBoxShadow: `0px 5px 15px 0px ${shadow(shadowColor, 0.08)}, 0px 15px 35px -5px ${shadow(shadowColor, 0.2)}`, + cardContentShadow: `0px 0px 2px 0px ${shadow(shadowColor, 0.08)}, 0px 1px 2px 0px ${shadow(shadowColor, 0.06)}`, + actionCardShadow: `0px 1px 4px 0px ${shadow(shadowColor, 0.12)}, 0px 4px 8px 0px ${shadow(shadowColor, 0.12)}`, + outlineButtonShadow: `0px 2px 3px -1px ${shadow(shadowColor, 0.08)}, 0px 1px 0px 0px ${shadow(shadowColor, 0.02)}`, + input: '0px 0px 1px 0px {{color}}', + focusRing: '0px 0px 0px 4px {{color}}', + badge: `0px 2px 0px -1px ${shadow(shadowColor, 0.04)}`, + tableBodyShadow: `0px 0px 2px 0px ${shadow(shadowColor, 0.08)}, 0px 1px 2px 0px ${shadow(shadowColor, 0.12)}, 0px 0px 0px 1px ${shadow(shadowColor, 0.06)}`, + segmentedControl: `0px 1px 2px 0px ${createAlphaColorMixString(shadowColor, 8)}`, + switchControl: `0px 2px 2px -1px ${shadow(shadowColor, 0.06)}, 0px 0px 0px 1px ${shadow(shadowColor, 0.06)}, 0px 4px 4px -2px ${shadow(shadowColor, 0.06)}`, + }; +}; + +// Default shadows using black shadow color +export const shadows = Object.freeze(createShadowSet()); From e918d24f514eb0e88671528873b350be7900bd6c Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Fri, 11 Jul 2025 16:35:42 -0400 Subject: [PATCH 2/5] check for colorMix support --- packages/clerk-js/src/ui/foundations/shadows.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/clerk-js/src/ui/foundations/shadows.ts b/packages/clerk-js/src/ui/foundations/shadows.ts index 09d26581329..e716b09e2ca 100644 --- a/packages/clerk-js/src/ui/foundations/shadows.ts +++ b/packages/clerk-js/src/ui/foundations/shadows.ts @@ -1,8 +1,11 @@ import { createAlphaColorMixString } from '../utils/colors/utils'; import { clerkCssVar } from '../utils/cssVariables'; +import { cssSupports } from '../utils/cssSupports'; const shadow = (color: string, alpha: number) => - clerkCssVar('color-shadow', createAlphaColorMixString(color, alpha * 100)); + cssSupports.modernColor() + ? clerkCssVar('color-shadow', createAlphaColorMixString(color, alpha * 100)) + : `rgba(0, 0, 0, ${alpha})`; /** * Creates a complete set of shadows using the provided shadow color From 0f085f611d3e2c9a1b75b3b58fc207e56a726f7b Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Fri, 11 Jul 2025 16:57:16 -0400 Subject: [PATCH 3/5] shadow generation --- .../src/ui/customizables/parseVariables.ts | 9 ++-- .../clerk-js/src/ui/foundations/shadows.ts | 45 ++++++++++++------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/packages/clerk-js/src/ui/customizables/parseVariables.ts b/packages/clerk-js/src/ui/customizables/parseVariables.ts index 474a8340e27..eafa1691826 100644 --- a/packages/clerk-js/src/ui/customizables/parseVariables.ts +++ b/packages/clerk-js/src/ui/customizables/parseVariables.ts @@ -4,10 +4,11 @@ import { spaceScaleKeys } from '../foundations/sizes'; import type { fontWeights } from '../foundations/typography'; import { colors } from '../utils/colors'; import { colorOptionToThemedAlphaScale, colorOptionToThemedLightnessScale } from '../utils/colors/scales'; +import { createAlphaColorMixString } from '../utils/colors/utils'; import { cssSupports } from '../utils/cssSupports'; import { fromEntries } from '../utils/fromEntries'; import { removeUndefinedProps } from '../utils/removeUndefinedProps'; -import { createShadowSet } from '../foundations/shadows'; +import { createShadowSet, generateShadow } from '../foundations/shadows'; export const createColorScales = (theme: Theme) => { const variables = removeInvalidValues(theme.variables || {}); @@ -194,6 +195,8 @@ export const createShadowsUnits = (theme: Theme) => { return; } - // Use the shared shadow creation function with the custom shadow color - return createShadowSet(shadowColor); + return createShadowSet( + shadowColor, + generateShadow((color, alpha) => createAlphaColorMixString(color, alpha * 100)), + ); }; diff --git a/packages/clerk-js/src/ui/foundations/shadows.ts b/packages/clerk-js/src/ui/foundations/shadows.ts index e716b09e2ca..0c0c3be7b5a 100644 --- a/packages/clerk-js/src/ui/foundations/shadows.ts +++ b/packages/clerk-js/src/ui/foundations/shadows.ts @@ -2,34 +2,45 @@ import { createAlphaColorMixString } from '../utils/colors/utils'; import { clerkCssVar } from '../utils/cssVariables'; import { cssSupports } from '../utils/cssSupports'; -const shadow = (color: string, alpha: number) => - cssSupports.modernColor() - ? clerkCssVar('color-shadow', createAlphaColorMixString(color, alpha * 100)) - : `rgba(0, 0, 0, ${alpha})`; +type ShadowGenerator = (color: string, alpha: number) => string; + +const generateShadow = + (fn: (color: string, alpha: number) => string): ShadowGenerator => + (color: string, alpha: number) => + cssSupports.modernColor() ? fn(color, alpha) : `rgba(0, 0, 0, ${alpha})`; /** * Creates a complete set of shadows using the provided shadow color * @param shadowColor - The base color to use for shadows (defaults to black) - * @param highlightColor - The color to use for inset highlights (defaults to white) + * @param shadowGenerator - Function to generate shadow colors with alpha (defaults to CSS variable-based generator) * @returns Object containing all shadow definitions */ -export const createShadowSet = (shadowColor: string = '#000000', highlightColor: string = '#FFFFFF') => { +export const createShadowSet = ( + shadowColor: string = '#000000', + shadowGenerator: ShadowGenerator = generateShadow((color, alpha) => + createAlphaColorMixString(clerkCssVar('color-shadow', color), alpha * 100), + ), +) => { + const highlightColor = '#FFFFFF'; return { - menuShadow: `0px 5px 15px 0px ${shadow(shadowColor, 0.08)}, 0px 15px 35px -5px ${shadow(shadowColor, 0.2)}`, - fabShadow: `0px 12px 24px ${shadow(shadowColor, 0.32)}`, - buttonShadow: `0px 1px 1px 0px ${shadow(highlightColor, 0.07)} inset, 0px 2px 3px 0px ${shadow(shadowColor, 0.2)}, 0px 1px 1px 0px ${shadow(shadowColor, 0.24)}`, - cardBoxShadow: `0px 5px 15px 0px ${shadow(shadowColor, 0.08)}, 0px 15px 35px -5px ${shadow(shadowColor, 0.2)}`, - cardContentShadow: `0px 0px 2px 0px ${shadow(shadowColor, 0.08)}, 0px 1px 2px 0px ${shadow(shadowColor, 0.06)}`, - actionCardShadow: `0px 1px 4px 0px ${shadow(shadowColor, 0.12)}, 0px 4px 8px 0px ${shadow(shadowColor, 0.12)}`, - outlineButtonShadow: `0px 2px 3px -1px ${shadow(shadowColor, 0.08)}, 0px 1px 0px 0px ${shadow(shadowColor, 0.02)}`, + menuShadow: `0px 5px 15px 0px ${shadowGenerator(shadowColor, 0.08)}, 0px 15px 35px -5px ${shadowGenerator(shadowColor, 0.2)}`, + fabShadow: `0px 12px 24px ${shadowGenerator(shadowColor, 0.32)}`, + buttonShadow: `0px 1px 1px 0px ${shadowGenerator(highlightColor, 0.07)} inset, 0px 2px 3px 0px ${shadowGenerator(shadowColor, 0.2)}, 0px 1px 1px 0px ${shadowGenerator(shadowColor, 0.24)}`, + cardBoxShadow: `0px 5px 15px 0px ${shadowGenerator(shadowColor, 0.08)}, 0px 15px 35px -5px ${shadowGenerator(shadowColor, 0.2)}`, + cardContentShadow: `0px 0px 2px 0px ${shadowGenerator(shadowColor, 0.08)}, 0px 1px 2px 0px ${shadowGenerator(shadowColor, 0.06)}`, + actionCardShadow: `0px 1px 4px 0px ${shadowGenerator(shadowColor, 0.12)}, 0px 4px 8px 0px ${shadowGenerator(shadowColor, 0.12)}`, + outlineButtonShadow: `0px 2px 3px -1px ${shadowGenerator(shadowColor, 0.08)}, 0px 1px 0px 0px ${shadowGenerator(shadowColor, 0.02)}`, input: '0px 0px 1px 0px {{color}}', focusRing: '0px 0px 0px 4px {{color}}', - badge: `0px 2px 0px -1px ${shadow(shadowColor, 0.04)}`, - tableBodyShadow: `0px 0px 2px 0px ${shadow(shadowColor, 0.08)}, 0px 1px 2px 0px ${shadow(shadowColor, 0.12)}, 0px 0px 0px 1px ${shadow(shadowColor, 0.06)}`, - segmentedControl: `0px 1px 2px 0px ${createAlphaColorMixString(shadowColor, 8)}`, - switchControl: `0px 2px 2px -1px ${shadow(shadowColor, 0.06)}, 0px 0px 0px 1px ${shadow(shadowColor, 0.06)}, 0px 4px 4px -2px ${shadow(shadowColor, 0.06)}`, + badge: `0px 2px 0px -1px ${shadowGenerator(shadowColor, 0.04)}`, + tableBodyShadow: `0px 0px 2px 0px ${shadowGenerator(shadowColor, 0.08)}, 0px 1px 2px 0px ${shadowGenerator(shadowColor, 0.12)}, 0px 0px 0px 1px ${shadowGenerator(shadowColor, 0.06)}`, + segmentedControl: `0px 1px 2px 0px ${shadowGenerator(shadowColor, 0.08)}`, + switchControl: `0px 2px 2px -1px ${shadowGenerator(shadowColor, 0.06)}, 0px 0px 0px 1px ${shadowGenerator(shadowColor, 0.06)}, 0px 4px 4px -2px ${shadowGenerator(shadowColor, 0.06)}`, }; }; // Default shadows using black shadow color export const shadows = Object.freeze(createShadowSet()); + +// Export the generator functions for use in other modules +export { generateShadow }; From ffc02178abbf437399fafa981e5862429cf1bfe4 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Fri, 11 Jul 2025 17:06:10 -0400 Subject: [PATCH 4/5] update comment --- packages/types/src/appearance.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index 5d1884e5303..a388f2cb949 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -731,8 +731,8 @@ export type Variables = { */ colorRing?: CssColor; /** - * The color of the shadow used in card components. - * @default 'rgba(25, 28, 33, 0.20)' + * The color used as the base for all shadows. + * @default '#000000' */ colorShadow?: CssColor; /** From e4edc2b99626a6226f900aca70f63ce7faf3c2b9 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 14 Jul 2025 09:11:28 -0400 Subject: [PATCH 5/5] update shadow description --- packages/types/src/appearance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index a388f2cb949..b5fb5c3f6a3 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -731,7 +731,7 @@ export type Variables = { */ colorRing?: CssColor; /** - * The color used as the base for all shadows. + * The color used as the base for shadows. * @default '#000000' */ colorShadow?: CssColor;