Skip to content

Commit ecae865

Browse files
committed
fixup! feat!: Paragon 23 and External CSS support
1 parent 3724a9b commit ecae865

File tree

6 files changed

+67
-50
lines changed

6 files changed

+67
-50
lines changed

docs/how_tos/theming.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@ better understanding.
7373

7474
### Configuration options
7575

76-
To enable `@openedx/brand-openedx` overrides, the `theme` site
77-
configuration setting may be configured with the following:
78-
79-
| Property | Data Type | Description |
80-
| ----------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------- |
81-
| `core` | Object | Metadata about the core styles from `@openedx/brand-openedx`. |
82-
| `core.url` | String | URL for the `core.css` file from `@openedx/brand-openedx`. |
83-
| `defaults` | Object | Mapping of theme variants to Paragon's default supported light and dark theme variants. |
84-
| `defaults.light` | String | Default `light` theme variant from the theme variants in the `variants` object. |
85-
| `defaults.dark` | String | Default `dark` theme variant from the theme variants in the `variants` object. |
86-
| `variants` | Object | Metadata about each supported theme variant. |
87-
| `variants.light` | Object | Metadata about the light theme variant styles from `@openedx/brand-openedx`. |
88-
| `variants.light.url` | String | URL for the `light.css` file from `@openedx/brand-openedx`. |
89-
| `variants.dark` | Object | Metadata about the dark theme variant styles from `@openedx/brand-openedx`. |
90-
| `variants.dark.url` | String | URL for the `dark.css` file from `@openedx/brand-openedx`. |
76+
To use a custom theme, the `theme` site configuration setting may be configured
77+
with the following:
78+
79+
| Property | Data Type | Description |
80+
| ----------------------------------- | --------- | --------------------------------------------------------------------------------------- |
81+
| `core` | Object | Metadata about the core theme's core styles . |
82+
| `core.url` | String | URL for the theme's core stylesheet. |
83+
| `defaults` | Object | Mapping of theme variants to Paragon's default supported light and dark theme variants. |
84+
| `defaults.light` | String | Default `light` theme variant from the theme variants in the `variants` object. |
85+
| `defaults.dark` | String | Default `dark` theme variant from the theme variants in the `variants` object. |
86+
| `variants` | Object | Metadata about each supported theme variant. |
87+
| `variants.light` | Object | Metadata about the theme's light variant styles. |
88+
| `variants.light.url` | String | URL for the theme's light variant stylesheet. |
89+
| `variants.dark` | Object | Metadata about the theme's dark variant styles. |
90+
| `variants.dark.url` | String | URL for the theme's dark variant styles. |
9191

9292
The `dark` theme variant is optional.
9393

runtime/react/hooks/theme/useTheme.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ describe('useTheme', () => {
158158
unmount();
159159
});
160160

161-
it('should return themeVariant undefined if can not configure the default theme or fallback in the light theme', () => {
161+
it('should return themeVariant undefined if a default variant cannot be configured', () => {
162162
jest.spyOn(config, 'getSiteConfig').mockReturnValue({
163163
...baseSiteConfig,
164164
theme: {
@@ -192,7 +192,10 @@ describe('useTheme', () => {
192192
...baseSiteConfig,
193193
theme: {
194194
...theme,
195-
defaults: { dark: 'dark' },
195+
defaults: {
196+
light: 'light',
197+
dark: 'dark'
198+
},
196199
variants: {
197200
light: theme.variants.light,
198201
green: { url: 'green-url' }

runtime/react/hooks/theme/useTheme.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,16 @@ const useTheme = () => {
9999
core: themeCore,
100100
defaults: themeVariantDefaults,
101101
variants: themeVariants,
102-
} = themeConfig ?? {};
102+
} = themeConfig;
103103
const initialThemeState = {
104104
isThemeLoaded: false,
105105
themeVariant: getDefaultThemeVariant(themeVariants, themeVariantDefaults)?.name,
106106
};
107107
const [themeState, dispatch] = useReducer(themeReducer, initialThemeState);
108108

109-
const [isThemeCoreLoaded, setIsthemeCoreLoaded] = useState(false);
109+
const [isThemeCoreLoaded, setIsThemeCoreLoaded] = useState(false);
110110
const onLoadThemeCore = useCallback(() => {
111-
setIsthemeCoreLoaded(true);
111+
setIsThemeCoreLoaded(true);
112112
}, []);
113113

114114
const [hasLoadedThemeVariants, setHasLoadedThemeVariants] = useState(false);

runtime/react/hooks/theme/useThemeConfig.test.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ describe('useThemeConfig', () => {
1212
});
1313

1414
it.each([
15-
[undefined, undefined],
16-
[{}, undefined],
15+
[undefined, {}],
16+
[{}, {}],
1717
])('handles when `siteConfig.theme` is not present (%s)', (theme, expectedURLConfig) => {
1818
jest.spyOn(config, 'getSiteConfig').mockReturnValue({
1919
...baseSiteConfig,
@@ -24,21 +24,34 @@ describe('useThemeConfig', () => {
2424
});
2525

2626
describe('when `siteConfig.theme` is present', () => {
27-
it('returns expected undefined when variants are not present', () => {
27+
it('returns empty object if at least one variant is not defined', () => {
2828
jest.spyOn(config, 'getSiteConfig').mockReturnValue({
2929
...baseSiteConfig,
3030
theme: {
31-
core: {
32-
url: 'brand-core.css',
33-
},
34-
defaults: {
35-
light: 'light',
36-
},
37-
variants: {},
31+
core: undefined,
32+
variants: {}
33+
},
34+
});
35+
const { result } = renderHook(() => useThemeConfig());
36+
expect(result.current).toStrictEqual({});
37+
});
38+
it('returns expected object when nothing but the light variant is defined', () => {
39+
jest.spyOn(config, 'getSiteConfig').mockReturnValue({
40+
...baseSiteConfig,
41+
theme: {
42+
variants: {
43+
light: { url: 'light.css' },
44+
}
3845
},
3946
});
4047
const { result } = renderHook(() => useThemeConfig());
41-
expect(result.current).toBe(undefined);
48+
expect(result.current).toStrictEqual({
49+
core: undefined,
50+
defaults: undefined,
51+
variants: {
52+
light: { url: 'light.css' },
53+
}
54+
});
4255
});
4356

4457
it('returns expected object when configuration is valid', () => {
@@ -59,21 +72,19 @@ describe('useThemeConfig', () => {
5972
},
6073
});
6174
const { result } = renderHook(() => useThemeConfig());
62-
expect(result.current).toEqual(
63-
expect.objectContaining({
64-
core: {
65-
url: 'core.css',
66-
},
67-
defaults: {
68-
light: 'light',
69-
},
70-
variants: {
71-
light: {
72-
url: 'light.css',
73-
},
75+
expect(result.current).toStrictEqual({
76+
core: {
77+
url: 'core.css',
78+
},
79+
defaults: {
80+
light: 'light',
81+
},
82+
variants: {
83+
light: {
84+
url: 'light.css',
7485
},
75-
}),
76-
);
86+
},
87+
});
7788
});
7889
});
7990
});

runtime/react/hooks/theme/useThemeConfig.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { useMemo } from 'react';
22

3-
import { isEmptyObject } from './utils';
3+
import { Theme } from '../../../../types';
44
import { getSiteConfig } from '../../../config';
5+
import { isEmptyObject } from './utils';
56

67
/**
78
* Custom React hook that retrieves the theme configuration.
89
*
10+
* Configuration is considered entirely invalid if it doesn't define at least one variant, including core.
11+
*
912
* Example:
1013
*
1114
* const themeConfig = useThemeConfig();
@@ -14,11 +17,11 @@ import { getSiteConfig } from '../../../config';
1417
* console.log(themeConfig.variants['dark'].url); // Outputs the URL of the dark theme variant CSS
1518
* }
1619
*/
17-
const useThemeConfig = () => useMemo(() => {
20+
const useThemeConfig = (): Theme => useMemo(() => {
1821
const { theme } = getSiteConfig();
1922

20-
if (!theme?.core?.url || isEmptyObject(theme.defaults) || isEmptyObject(theme.variants)) {
21-
return;
23+
if (!theme || (isEmptyObject(theme.core) && isEmptyObject(theme.variants))) {
24+
return {};
2225
}
2326

2427
return {

types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export type ThemeVariants = Record<string, ThemeVariant>;
9494

9595
export interface Theme {
9696
core?: ThemeVariant,
97-
defaults?: Partial<ThemeDefaults>,
97+
defaults?: ThemeDefaults,
9898
variants?: ThemeVariants,
9999
}
100100

0 commit comments

Comments
 (0)