Skip to content

Commit 45af5b1

Browse files
fix(theme): wait for browser system preference
1 parent 8af2562 commit 45af5b1

File tree

2 files changed

+20
-17
lines changed

2 files changed

+20
-17
lines changed

lib/context/theme.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
1-
import { createContext, useContext } from 'react';
1+
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
22

3-
import { Callback } from 'lib/model/callback';
3+
import { Callback } from 'lib/callback';
44

55
export type Theme = 'system' | 'dark' | 'light';
66
export interface ThemeContextType {
7-
dark: boolean;
87
theme: Theme;
98
setTheme: Callback<Theme>;
109
}
1110

1211
export const ThemeContext = createContext<ThemeContextType>({
13-
dark: false,
1412
theme: 'system',
1513
setTheme: () => {},
1614
});
1715

18-
export function useTheme(): ThemeContextType {
19-
return useContext(ThemeContext);
16+
export function useTheme(): ThemeContextType & { dark: boolean } {
17+
const { theme, setTheme } = useContext(ThemeContext);
18+
const [dark, setDark] = useState(theme === 'dark');
19+
useEffect(() => {
20+
setDark(
21+
theme === 'dark' ||
22+
(theme === 'system' &&
23+
typeof matchMedia !== 'undefined' &&
24+
matchMedia('(prefers-color-scheme: dark)').matches)
25+
);
26+
}, [theme]);
27+
return useMemo(() => ({ theme, setTheme, dark }), [theme, setTheme, dark]);
2028
}

pages/_app.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export default function App({ Component, pageProps }: AppProps): JSX.Element {
3131
const { data, error } = useSWR<UserJSON, APIError>('/api/account', fetcher);
3232
// TODO: Hoist the i18n locale to the top-level of the app (or trigger an
3333
// effect from within the `withI18n` HOC) to properly set these `langs`.
34-
const user = useMemo(() => data ? User.fromJSON(data) : emptyUser, [data]);
34+
const user = useMemo(() => (data ? User.fromJSON(data) : emptyUser), [data]);
3535
const loggedIn = useMemo(() => {
3636
if (user.id) {
3737
userLoaded.current = true;
@@ -89,7 +89,10 @@ export default function App({ Component, pageProps }: AppProps): JSX.Element {
8989
'/api/account/orgs',
9090
fetcher
9191
);
92-
const orgsLoaded = useMemo(() => !!orgsData || !!orgsError, [orgsData, orgsError]);
92+
const orgsLoaded = useMemo(
93+
() => !!orgsData || !!orgsError,
94+
[orgsData, orgsError]
95+
);
9396
const orgs = useMemo(
9497
() => (orgsData ? orgsData.map((o) => Org.fromJSON(o)) : []),
9598
[orgsData]
@@ -112,14 +115,6 @@ export default function App({ Component, pageProps }: AppProps): JSX.Element {
112115
);
113116

114117
const [theme, setTheme] = useState<Theme>('system');
115-
const dark = useMemo(
116-
() =>
117-
theme === 'dark' ||
118-
(theme === 'system' &&
119-
typeof matchMedia !== 'undefined' &&
120-
matchMedia('(prefers-color-scheme: dark)').matches),
121-
[theme]
122-
);
123118
useEffect(() => {
124119
if (theme === 'dark') {
125120
document.documentElement.classList.add('dark');
@@ -143,7 +138,7 @@ export default function App({ Component, pageProps }: AppProps): JSX.Element {
143138
}, [theme]);
144139

145140
return (
146-
<ThemeContext.Provider value={{ dark, theme, setTheme }}>
141+
<ThemeContext.Provider value={{ theme, setTheme }}>
147142
<SWRConfig value={{ fetcher }}>
148143
<UserContext.Provider
149144
value={{ user, orgs, updateUser, updateOrg, loggedIn, orgsLoaded }}

0 commit comments

Comments
 (0)