Skip to content

Commit 9017f3b

Browse files
committed
support CSS modules
1 parent 7f1c984 commit 9017f3b

File tree

2 files changed

+42
-18
lines changed

2 files changed

+42
-18
lines changed

.tkb

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@
2424
"-FlzW8htLo-6jz5-ZqjEx": {
2525
"id": "-FlzW8htLo-6jz5-ZqjEx",
2626
"description": "update examples to showcase edge cases",
27+
"columnId": "column-doing"
28+
},
29+
"p1R-Q4atxMo-29mSa7mb6": {
30+
"id": "p1R-Q4atxMo-29mSa7mb6",
31+
"description": "Remove scoped packages from turborepo-template",
2732
"columnId": "column-todo"
2833
},
29-
"5fLtFF1sHPxsPjq-wWOxv": {
30-
"id": "5fLtFF1sHPxsPjq-wWOxv",
31-
"description": "Fix turbo-repo template bug - replacing only first doc link in readme --- look at the [doc] with [TypeDoc]",
34+
"a7ksr41sN7kQNaH8Io-dV": {
35+
"id": "a7ksr41sN7kQNaH8Io-dV",
36+
"description": "Add support for css modules",
3237
"columnId": "column-todo"
3338
}
3439
},
@@ -37,14 +42,16 @@
3742
"id": "column-todo",
3843
"title": "To do",
3944
"tasksIds": [
40-
"-FlzW8htLo-6jz5-ZqjEx",
41-
"5fLtFF1sHPxsPjq-wWOxv"
45+
"p1R-Q4atxMo-29mSa7mb6",
46+
"a7ksr41sN7kQNaH8Io-dV"
4247
]
4348
},
4449
{
4550
"id": "column-doing",
4651
"title": "Doing",
47-
"tasksIds": []
52+
"tasksIds": [
53+
"-FlzW8htLo-6jz5-ZqjEx"
54+
]
4855
},
4956
{
5057
"id": "column-done",

lib/nthul/src/client/theme-switcher/theme-switcher.tsx

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export interface ThemeSwitcherProps {
1111
dontSync?: boolean;
1212
/** force apply CSS transition property to all the elements during theme switching. E.g., `all .3s` */
1313
themeTransition?: string;
14+
/** provide styles object if you are using CSS/SCSS modules. */
15+
styles?: Record<string, string>;
1416
}
1517

1618
function useMediaQuery(setThemeState: SetStateAction<ThemeState>) {
@@ -77,13 +79,36 @@ function modifyTransition(themeTransition = "none", targetId?: string) {
7779
};
7880
}
7981

82+
export interface ApplyClassesProps {
83+
targets: (HTMLElement | null)[];
84+
theme: string;
85+
resolvedColorScheme: "light" | "dark";
86+
styles?: Record<string, string>;
87+
}
88+
89+
function applyClasses({ targets, theme, resolvedColorScheme, styles }: ApplyClassesProps) {
90+
let cls = ["dark", "light", theme, resolvedColorScheme];
91+
if (styles) cls = cls.map(c => styles[c]);
92+
93+
targets.forEach(t => {
94+
t?.classList.remove(cls[0]); // dark
95+
t?.classList.remove(cls[1]); // light
96+
t?.classList.forEach(cls => {
97+
if (cls.match(/(^|_)th-/)) t.classList.remove(cls);
98+
});
99+
t?.classList.add(`th-${cls[2]}`); // theme
100+
t?.classList.add(cls[3]); // resolvedColorScheme
101+
});
102+
}
103+
80104
export interface UpdateDOMProps {
81105
targetId?: string;
82106
themeState: ThemeState;
83107
dontSync?: boolean;
108+
styles?: Record<string, string>;
84109
}
85110

86-
function updateDOM({ targetId, themeState, dontSync }: UpdateDOMProps) {
111+
function updateDOM({ targetId, themeState, dontSync, styles }: UpdateDOMProps) {
87112
const { theme, colorSchemePreference: csp, systemColorScheme: scs } = themeState;
88113
const resolvedColorScheme = csp === "system" ? scs : csp;
89114
const key = targetId ?? DEFAULT_ID;
@@ -95,15 +120,7 @@ function updateDOM({ targetId, themeState, dontSync }: UpdateDOMProps) {
95120
/** do not update documentElement for local targets */
96121
const targets = targetId ? [target] : [target, document.documentElement];
97122

98-
targets.forEach(t => {
99-
t?.classList.remove("dark");
100-
t?.classList.remove("light");
101-
t?.classList.forEach(cls => {
102-
if (cls.startsWith("th-")) t.classList.remove(cls);
103-
});
104-
t?.classList.add(`th-${theme}`);
105-
t?.classList.add(resolvedColorScheme);
106-
});
123+
applyClasses({ targets, styles, resolvedColorScheme, theme });
107124

108125
if (shoulCreateCookie) document.cookie = `${key}=${theme},${resolvedColorScheme}; max-age=31536000; SameSite=Strict;`;
109126
}
@@ -112,7 +129,7 @@ function updateDOM({ targetId, themeState, dontSync }: UpdateDOMProps) {
112129
* The core ThemeSwitcher component wich applies classes and transitions.
113130
* Cookies are set only if corresponding ServerTarget is detected.
114131
*/
115-
export function ThemeSwitcher({ targetId, dontSync, themeTransition }: ThemeSwitcherProps) {
132+
export function ThemeSwitcher({ targetId, dontSync, themeTransition, styles }: ThemeSwitcherProps) {
116133
if (targetId === "") throw new Error("id can not be an empty string");
117134
const [themeState, setThemeState] = useRGS<ThemeState>(targetId ?? DEFAULT_ID, DEFAULT_THEME_STATE);
118135

@@ -123,7 +140,7 @@ export function ThemeSwitcher({ targetId, dontSync, themeTransition }: ThemeSwit
123140
/** update DOM and storage */
124141
React.useEffect(() => {
125142
const restoreTransitions = modifyTransition(themeTransition, targetId);
126-
updateDOM({ targetId, themeState, dontSync });
143+
updateDOM({ targetId, themeState, dontSync, styles });
127144
if (!dontSync && tInit < Date.now() - 300) {
128145
// save to localStorage
129146
const { theme, colorSchemePreference } = themeState;

0 commit comments

Comments
 (0)