Skip to content

Commit 8f9dd6d

Browse files
committed
Add option to disable baseTheme in appearance
Introduces support for setting `baseTheme: false` in appearance and globalAppearance, allowing users to disable the default base theme. Updates tests, documentation, and internal logic to handle the new option and renames `polishedAppearance` to `baseTheme` for clarity.
1 parent 70afacd commit 8f9dd6d

File tree

5 files changed

+90
-9
lines changed

5 files changed

+90
-9
lines changed

packages/clerk-js/sandbox/app.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ function appearanceVariableOptions() {
192192
const updateVariables = () => {
193193
void Clerk.__unstable__updateProps({
194194
appearance: {
195+
// Preserve existing appearance properties like baseTheme
196+
...Clerk.__internal_getOption('appearance'),
195197
variables: Object.fromEntries(
196198
Object.entries(variableInputs).map(([key, input]) => {
197199
sessionStorage.setItem(key, input.value);
@@ -349,6 +351,9 @@ void (async () => {
349351
...(componentControls.clerk.getProps() ?? {}),
350352
signInUrl: '/sign-in',
351353
signUpUrl: '/sign-up',
354+
// appearance: {
355+
// baseTheme: false,
356+
// },
352357
});
353358
renderCurrentRoute();
354359
updateVariables();

packages/clerk-js/src/ui/polishedAppearance.ts renamed to packages/clerk-js/src/ui/baseTheme.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ const inputStyles = (theme: InternalTheme) => ({
9393
}),
9494
});
9595

96-
export const polishedAppearance: Appearance = {
96+
export const baseTheme: Appearance = {
9797
elements: ({ theme }: { theme: InternalTheme }): Elements => {
9898
return {
9999
button: {

packages/clerk-js/src/ui/customizables/__tests__/parseAppearance.test.tsx

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ describe('AppearanceProvider layout flows', () => {
338338
expect(result.current.parsedLayout.socialButtonsVariant).toBe('blockButton');
339339
});
340340

341-
it('removes the polishedAppearance when simpleStyles is passed to globalAppearance', () => {
341+
it('removes the baseTheme when simpleStyles is passed to globalAppearance', () => {
342342
const wrapper = ({ children }) => (
343343
<AppearanceProvider
344344
appearanceKey='signIn'
@@ -359,7 +359,7 @@ describe('AppearanceProvider layout flows', () => {
359359
expect(result.current.parsedElements[0]['alert'].backgroundColor).toBe(themeAColor);
360360
});
361361

362-
it('removes the polishedAppearance when simpleStyles is passed to appearance', () => {
362+
it('removes the baseTheme when simpleStyles is passed to appearance', () => {
363363
const wrapper = ({ children }) => (
364364
<AppearanceProvider
365365
appearanceKey='signIn'
@@ -379,6 +379,72 @@ describe('AppearanceProvider layout flows', () => {
379379
//notice the "0" index, not "1" as it would be without simpleStyles
380380
expect(result.current.parsedElements[0]['alert'].backgroundColor).toBe(themeBColor);
381381
});
382+
383+
it('removes the baseTheme when baseTheme is set to false in globalAppearance', () => {
384+
const wrapper = ({ children }) => (
385+
<AppearanceProvider
386+
appearanceKey='signIn'
387+
globalAppearance={{
388+
baseTheme: false,
389+
elements: {
390+
alert: { backgroundColor: themeAColor },
391+
},
392+
}}
393+
>
394+
{children}
395+
</AppearanceProvider>
396+
);
397+
398+
const { result } = renderHook(() => useAppearance(), { wrapper });
399+
//notice the "0" index, not "1" as it would be without baseTheme
400+
expect(result.current.parsedElements[0]['alert'].backgroundColor).toBe(themeAColor);
401+
});
402+
403+
it('removes the baseTheme when baseTheme is set to false in appearance', () => {
404+
const wrapper = ({ children }) => (
405+
<AppearanceProvider
406+
appearanceKey='signIn'
407+
appearance={{
408+
baseTheme: false,
409+
elements: {
410+
alert: { backgroundColor: themeBColor },
411+
},
412+
}}
413+
>
414+
{children}
415+
</AppearanceProvider>
416+
);
417+
418+
const { result } = renderHook(() => useAppearance(), { wrapper });
419+
//notice the "0" index, not "1" as it would be without baseTheme
420+
expect(result.current.parsedElements[0]['alert'].backgroundColor).toBe(themeBColor);
421+
});
422+
423+
it('removes the baseTheme when baseTheme is set to false even with globalAppearance', () => {
424+
const wrapper = ({ children }) => (
425+
<AppearanceProvider
426+
appearanceKey='signIn'
427+
globalAppearance={{
428+
elements: {
429+
alert: { backgroundColor: themeAColor },
430+
},
431+
}}
432+
appearance={{
433+
baseTheme: false,
434+
elements: {
435+
alert: { backgroundColor: themeBColor },
436+
},
437+
}}
438+
>
439+
{children}
440+
</AppearanceProvider>
441+
);
442+
443+
const { result } = renderHook(() => useAppearance(), { wrapper });
444+
//notice the "0" index for first element and "1" for second - baseTheme is disabled
445+
expect(result.current.parsedElements[0]['alert'].backgroundColor).toBe(themeAColor);
446+
expect(result.current.parsedElements[1]['alert'].backgroundColor).toBe(themeBColor);
447+
});
382448
});
383449

384450
describe('AppearanceProvider captcha', () => {

packages/clerk-js/src/ui/customizables/parseAppearance.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { fastDeepMergeAndReplace } from '@clerk/shared/utils';
22
import type { Appearance, CaptchaAppearanceOptions, DeepPartial, Elements, Layout, Theme } from '@clerk/types';
33

4+
import { baseTheme } from '../baseTheme';
45
import { createInternalTheme, defaultInternalTheme } from '../foundations';
56
import type { InternalTheme } from '../styledSystem';
67
import {
@@ -80,9 +81,10 @@ export const parseAppearance = (cascade: AppearanceCascade): ParsedAppearance =>
8081
!appearanceList.find(a => {
8182
//@ts-expect-error not public api
8283
return !!a.simpleStyles;
83-
})
84+
}) &&
85+
!appearanceList.find(a => a.baseTheme === false)
8486
) {
85-
// appearanceList.unshift(polishedAppearance);
87+
appearanceList.unshift(baseTheme);
8688
}
8789

8890
const parsedElements = parseElements(
@@ -103,9 +105,12 @@ const expand = (theme: Theme | undefined, cascade: any[]) => {
103105
return;
104106
}
105107

106-
(Array.isArray(theme.baseTheme) ? theme.baseTheme : [theme.baseTheme]).forEach(baseTheme =>
107-
expand(baseTheme as Theme, cascade),
108-
);
108+
// Only expand baseTheme if it's not false
109+
if (theme.baseTheme !== false) {
110+
(Array.isArray(theme.baseTheme) ? theme.baseTheme : [theme.baseTheme]).forEach(baseTheme =>
111+
expand(baseTheme as Theme, cascade),
112+
);
113+
}
109114

110115
cascade.push(theme);
111116
};

packages/types/src/appearance.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,11 +812,16 @@ export type Theme = {
812812
/**
813813
* A theme used as the base theme for the components.
814814
* For further customisation, you can use the {@link Theme.layout}, {@link Theme.variables} and {@link Theme.elements} props.
815+
* Set to `false` to disable the base theme.
815816
* @example
816817
* import { dark } from "@clerk/themes";
817818
* appearance={{ baseTheme: dark }}
819+
*
820+
* @example
821+
* // Disable base theme
822+
* appearance={{ baseTheme: false }}
818823
*/
819-
baseTheme?: BaseTheme | BaseTheme[];
824+
baseTheme?: BaseTheme | BaseTheme[] | false;
820825
/**
821826
* Configuration options that affect the layout of the components, allowing
822827
* customizations that hard to implement with just CSS.

0 commit comments

Comments
 (0)