Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions integration/tests/appearance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ test.describe('appearance prop', () => {
return (
<div key={name}>
<h2>{name}</h2>
<SignIn appearance={{ baseTheme: theme }} />
<SignUp appearance={{ baseTheme: theme }} />
<SignIn appearance={{ theme }} />
<SignUp appearance={{ theme }} />
</div>
);
});
Expand Down
32 changes: 16 additions & 16 deletions packages/react/src/__tests__/isomorphicClerk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,29 +43,29 @@ describe('isomorphicClerk', () => {
const isomorphicClerk = new IsomorphicClerk({ publishableKey: 'pk_test_XXX' });
(isomorphicClerk as any).clerkjs = dummyClerkJS as any;

void isomorphicClerk.__unstable__updateProps({ appearance: { baseTheme: 'dark' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { baseTheme: 'light' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { baseTheme: 'purple' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { baseTheme: 'yellow' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { baseTheme: 'red' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { baseTheme: 'blue' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { baseTheme: 'green' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { theme: 'dark' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { theme: 'light' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { theme: 'purple' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { theme: 'yellow' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { theme: 'red' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { theme: 'blue' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { theme: 'green' } });
expect(propsHistory).toEqual([]);

vi.spyOn(isomorphicClerk, 'loaded', 'get').mockReturnValue(true);
isomorphicClerk.emitLoaded();
void isomorphicClerk.__unstable__updateProps({ appearance: { baseTheme: 'white' } });
void isomorphicClerk.__unstable__updateProps({ appearance: { theme: 'white' } });
await vi.runAllTimersAsync();

expect(propsHistory).toEqual([
{ appearance: { baseTheme: 'dark' } },
{ appearance: { baseTheme: 'light' } },
{ appearance: { baseTheme: 'purple' } },
{ appearance: { baseTheme: 'yellow' } },
{ appearance: { baseTheme: 'red' } },
{ appearance: { baseTheme: 'blue' } },
{ appearance: { baseTheme: 'green' } },
{ appearance: { baseTheme: 'white' } },
{ appearance: { theme: 'dark' } },
{ appearance: { theme: 'light' } },
{ appearance: { theme: 'purple' } },
{ appearance: { theme: 'yellow' } },
{ appearance: { theme: 'red' } },
{ appearance: { theme: 'blue' } },
{ appearance: { theme: 'green' } },
{ appearance: { theme: 'white' } },
]);
});

Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/contexts/__tests__/ClerkProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ describe('ClerkProvider', () => {
expectTypeOf({ ...defaultProps, appearance: {} }).toMatchTypeOf<ClerkProviderProps>();
});

it('includes variables, elements, layout baseTheme', () => {
it('includes variables, elements, layout, theme', () => {
expectTypeOf({
...defaultProps,
appearance: { elements: {}, variables: {}, layout: {}, baseTheme: dark },
appearance: { elements: {}, variables: {}, layout: {}, theme: dark },
}).toMatchTypeOf<ClerkProviderProps>();
});

Expand Down
35 changes: 0 additions & 35 deletions packages/shared/src/telemetry/events/__tests__/theme-usage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,41 +72,6 @@ describe('eventThemeUsage', () => {
});
});

it('should prioritize theme over deprecated baseTheme', () => {
const appearance = {
theme: 'clerk' as any, // String themes are valid at runtime
baseTheme: {
__type: 'prebuilt_appearance' as const,
name: 'shadcn',
},
};

const result = eventThemeUsage(appearance);

expect(result).toEqual({
event: EVENT_THEME_USAGE,
eventSamplingRate: EVENT_SAMPLING_RATE,
payload: { themeName: 'clerk' },
});
});

it('should use baseTheme when theme is not provided', () => {
const appearance = {
baseTheme: {
__type: 'prebuilt_appearance' as const,
name: 'shadcn',
},
};

const result = eventThemeUsage(appearance);

expect(result).toEqual({
event: EVENT_THEME_USAGE,
eventSamplingRate: EVENT_SAMPLING_RATE,
payload: { themeName: 'shadcn' },
});
});

it('should handle undefined appearance', () => {
const result = eventThemeUsage();

Expand Down
4 changes: 2 additions & 2 deletions packages/shared/src/telemetry/events/component-mounted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type EventPrebuiltComponent = ComponentMountedBase & {
appearanceProp: boolean;
elements: boolean;
variables: boolean;
baseTheme: boolean;
theme: boolean;
};

type EventComponentMounted = ComponentMountedBase & TelemetryEventRaw['payload'];
Expand All @@ -48,7 +48,7 @@ function createPrebuiltComponentEvent(event: typeof EVENT_COMPONENT_MOUNTED | ty
payload: {
component,
appearanceProp: Boolean(props?.appearance),
baseTheme: Boolean(props?.appearance?.baseTheme),
theme: Boolean(props?.appearance?.theme),
elements: Boolean(props?.appearance?.elements),
variables: Boolean(props?.appearance?.variables),
...additionalPayload,
Expand Down
3 changes: 1 addition & 2 deletions packages/shared/src/telemetry/events/theme-usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ function analyzeThemeUsage(appearance?: any): EventThemeUsage {
return {};
}

// Prioritize the new theme property over deprecated baseTheme
const themeProperty = appearance.theme || appearance.baseTheme;
const themeProperty = appearance.theme;

if (!themeProperty) {
return {};
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/Components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export const mountComponentRenderer = (
moduleManager: ModuleManager,
) => {
const options = { ..._options };
// Extract cssLayerName from baseTheme if present and move it to appearance level
// Extract cssLayerName from theme if present and move it to appearance level
if (options.appearance) {
options.appearance = extractCssLayerNameFromAppearance(options.appearance);
}
Expand Down
53 changes: 9 additions & 44 deletions packages/ui/src/customizables/__tests__/parseAppearance.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ const themeA = {
colorBackground: themeAColor,
colorInput: themeAColor,
colorInputForeground: themeAColor,
colorText: themeAColor,
colorForeground: themeAColor,
colorPrimaryForeground: themeAColor,
colorTextSecondary: themeAColor,
colorMutedForeground: themeAColor,
borderRadius: '1rem',
fontFamily: 'Comic Sans',
fontFamilyButtons: 'Comic Sans',
Expand All @@ -39,9 +39,9 @@ const themeB = {
colorBackground: themeBColor,
colorInput: themeBColor,
colorInputForeground: themeBColor,
colorText: themeBColor,
colorForeground: themeBColor,
colorPrimaryForeground: themeBColor,
colorTextSecondary: themeBColor,
colorMutedForeground: themeBColor,
borderRadius: '2rem',
fontFamily: 'Arial',
fontFamilyButtons: 'Arial',
Expand Down Expand Up @@ -338,7 +338,7 @@ describe('AppearanceProvider layout flows', () => {
expect(result.current.parsedLayout.socialButtonsVariant).toBe('blockButton');
});

it('removes the baseTheme when simpleStyles is passed to globalAppearance', () => {
it('removes the base theme when simpleStyles is passed to globalAppearance', () => {
const wrapper = ({ children }) => (
<AppearanceProvider
appearanceKey='signIn'
Expand All @@ -359,7 +359,7 @@ describe('AppearanceProvider layout flows', () => {
expect(result.current.parsedElements[0]['alert'].backgroundColor).toBe(themeAColor);
});

it('removes the baseTheme when simpleStyles is passed to appearance', () => {
it('removes the base theme when simpleStyles is passed to appearance', () => {
const wrapper = ({ children }) => (
<AppearanceProvider
appearanceKey='signIn'
Expand Down Expand Up @@ -479,7 +479,7 @@ describe('AppearanceProvider theme flows', () => {
);

const { result } = renderHook(() => useAppearance(), { wrapper });
// Should include clerk theme styles (baseTheme will be included)
// Should include clerk theme styles (base theme will be included)
expect(result.current.parsedElements.length).toBeGreaterThan(0);
});

Expand All @@ -500,42 +500,7 @@ describe('AppearanceProvider theme flows', () => {
expect(result.current.parsedElements.length).toBe(2);
});

it('theme property takes precedence over deprecated baseTheme', () => {
const wrapper = ({ children }) => (
<AppearanceProvider
appearanceKey='signIn'
appearance={{
theme: 'simple',
baseTheme: 'clerk', // This should be ignored
}}
>
{children}
</AppearanceProvider>
);

const { result } = renderHook(() => useAppearance(), { wrapper });
// Should include both simple theme and base theme (2 elements total)
expect(result.current.parsedElements.length).toBe(2);
});

it('maintains backward compatibility with baseTheme property', () => {
const wrapper = ({ children }) => (
<AppearanceProvider
appearanceKey='signIn'
appearance={{
baseTheme: 'simple',
}}
>
{children}
</AppearanceProvider>
);

const { result } = renderHook(() => useAppearance(), { wrapper });
// Should work the same as theme: 'simple' (2 elements total)
expect(result.current.parsedElements.length).toBe(2);
});

it('supports object-based themes with new theme property', () => {
it('supports object-based themes with theme property', () => {
const customTheme = {
elements: {
card: { backgroundColor: 'red' },
Expand All @@ -559,7 +524,7 @@ describe('AppearanceProvider theme flows', () => {
expect(result.current.parsedElements.some(el => el.card?.backgroundColor === 'red')).toBe(true);
});

it('supports array-based themes with new theme property', () => {
it('supports array-based themes with theme property', () => {
const themeA = {
elements: { card: { backgroundColor: 'red' } },
};
Expand Down
13 changes: 6 additions & 7 deletions packages/ui/src/customizables/parseAppearance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export type ParsedCaptcha = Required<CaptchaAppearanceOptions>;

type PublicAppearanceTopLevelKey = keyof Omit<
Appearance,
'baseTheme' | 'theme' | 'elements' | 'layout' | 'variables' | 'captcha' | 'cssLayerName'
'theme' | 'elements' | 'layout' | 'variables' | 'captcha' | 'cssLayerName'
>;

export type AppearanceCascade = {
Expand Down Expand Up @@ -105,15 +105,14 @@ const expand = (theme: Theme | undefined, cascade: any[]) => {
return;
}

// Use new 'theme' property if available, otherwise fall back to deprecated 'baseTheme'
const themeProperty = theme.theme !== undefined ? theme.theme : theme.baseTheme;
const themeProperty = theme.theme;

if (themeProperty !== undefined) {
(Array.isArray(themeProperty) ? themeProperty : [themeProperty]).forEach(baseTheme => {
if (typeof baseTheme === 'string') {
expand(getBaseTheme(baseTheme), cascade);
(Array.isArray(themeProperty) ? themeProperty : [themeProperty]).forEach(t => {
if (typeof t === 'string') {
expand(getBaseTheme(t), cascade);
} else {
expand(baseTheme as Theme, cascade);
expand(t as Theme, cascade);
}
});
}
Expand Down
33 changes: 8 additions & 25 deletions packages/ui/src/customizables/parseVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,7 @@ const createMutedForegroundColor = (variables: NonNullable<Theme['variables']>)
return colors.toHslaString(variables.colorMutedForeground);
}

if (variables.colorTextSecondary) {
return colors.toHslaString(variables.colorTextSecondary);
}

if (variables.colorForeground) {
return colors.makeTransparent(variables.colorForeground, 0.35);
}

return colors.makeTransparent(variables.colorText, 0.35);
return colors.makeTransparent(variables.colorForeground, 0.35);
};

export const createColorScales = (theme: Theme) => {
Expand Down Expand Up @@ -57,20 +49,12 @@ export const createColorScales = (theme: Theme) => {
primaryHover: colors.adjustForLightness(primaryScale?.primary500),
colorPrimaryForeground: variables.colorPrimaryForeground
? colors.toHslaString(variables.colorPrimaryForeground)
: variables.colorTextOnPrimaryBackground
? colors.toHslaString(variables.colorTextOnPrimaryBackground)
: undefined,
colorForeground: variables.colorForeground
? colors.toHslaString(variables.colorForeground)
: colors.toHslaString(variables.colorText),
: undefined,
colorForeground: colors.toHslaString(variables.colorForeground),
colorMutedForeground: createMutedForegroundColor(variables),
colorInputForeground: variables.colorInputForeground
? colors.toHslaString(variables.colorInputForeground)
: colors.toHslaString(variables.colorInputText),
colorInputForeground: colors.toHslaString(variables.colorInputForeground),
colorBackground: colors.toHslaString(variables.colorBackground),
colorInput: variables.colorInput
? colors.toHslaString(variables.colorInput)
: colors.toHslaString(variables.colorInputBackground),
colorInput: colors.toHslaString(variables.colorInput),
colorShimmer: colors.toHslaString(variables.colorShimmer),
colorMuted: variables.colorMuted ? colors.toHslaString(variables.colorMuted) : undefined,
colorRing: variables.colorRing ? colors.toHslaString(variables.colorRing) : undefined,
Expand Down Expand Up @@ -146,16 +130,15 @@ export const createRadiiUnits = (theme: Theme) => {
};

export const createSpaceScale = (theme: Theme) => {
const { spacing, spacingUnit } = theme.variables || {};
const spacingValue = spacing ?? spacingUnit;
if (spacingValue === undefined) {
const { spacing } = theme.variables || {};
if (spacing === undefined) {
return;
}
return fromEntries(
spaceScaleKeys.map(k => {
const num = Number.parseFloat(k.replace('x', '.'));
const percentage = (num / 0.5) * 0.125;
return [k, `calc(${spacingValue} * ${percentage})`];
return [k, `calc(${spacing} * ${percentage})`];
}),
);
};
Expand Down
Loading
Loading