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 11fe2c50ef4..6d44ca6bb6a 100644 --- a/packages/clerk-js/src/ui/customizables/parseVariables.ts +++ b/packages/clerk-js/src/ui/customizables/parseVariables.ts @@ -4,9 +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, generateShadow } from '../foundations/shadows'; export const createColorScales = (theme: Theme) => { const variables = removeInvalidValues(theme.variables || {}); @@ -186,3 +188,20 @@ 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; + } + + 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 96f46a467c2..0c0c3be7b5a 100644 --- a/packages/clerk-js/src/ui/foundations/shadows.ts +++ b/packages/clerk-js/src/ui/foundations/shadows.ts @@ -1,18 +1,46 @@ -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'; +import { cssSupports } from '../utils/cssSupports'; + +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 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', + shadowGenerator: ShadowGenerator = generateShadow((color, alpha) => + createAlphaColorMixString(clerkCssVar('color-shadow', color), alpha * 100), + ), +) => { + const highlightColor = '#FFFFFF'; + return { + 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 ${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 }; diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index e5feed944e8..c81622d2cb3 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -732,7 +732,7 @@ export type Variables = { colorRing?: CssColor; /** * The base shadow color used in the components. - * @default 'rgba(25, 28, 33, 0.20)' + * @default '#000000' */ colorShadow?: CssColor; /**