Skip to content

Commit 0c31648

Browse files
committed
control themes with next-themes and sync with chakra provider
1 parent 22b8aa7 commit 0c31648

File tree

6 files changed

+72
-26
lines changed

6 files changed

+72
-26
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"next-i18next": "^14.0.3",
5252
"next-mdx-remote": "^3.0.8",
5353
"next-sitemap": "^4.2.3",
54+
"next-themes": "^0.3.0",
5455
"prism-react-renderer": "1.1.0",
5556
"prismjs": "^1.27.0",
5657
"react": "^18.2.0",
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { PropsWithChildren, useMemo } from "react"
2+
import merge from "lodash/merge"
3+
import { useTheme as useNextTheme } from "next-themes"
4+
import { ColorMode, ColorModeContext, ThemeProvider } from "@chakra-ui/react"
5+
6+
import customTheme from "@/@chakra-ui/theme"
7+
8+
import { useLocaleDirection } from "@/hooks/useLocaleDirection"
9+
10+
function ChakraThemeProvider({ children }: PropsWithChildren) {
11+
// get the theme from next-themes
12+
const { resolvedTheme } = useNextTheme()
13+
14+
const direction = useLocaleDirection()
15+
16+
const theme = useMemo(() => merge(customTheme, { direction }), [direction])
17+
18+
return (
19+
<ThemeProvider theme={theme}>
20+
<ColorModeContext.Provider
21+
value={{
22+
colorMode: resolvedTheme as ColorMode,
23+
toggleColorMode: () => {},
24+
setColorMode: () => {},
25+
forced: true,
26+
}}
27+
>
28+
{children}
29+
</ColorModeContext.Provider>
30+
</ThemeProvider>
31+
)
32+
}
33+
34+
export default ChakraThemeProvider

src/components/Nav/useNav.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useRouter } from "next/router"
22
import { useTranslation } from "next-i18next"
3+
import { useTheme } from "next-themes"
34
import {
45
BsBook,
56
BsBuildings,
@@ -19,7 +20,6 @@ import {
1920
} from "react-icons/bs"
2021
import { PiFlask, PiUsersFourLight } from "react-icons/pi"
2122
import {
22-
useColorMode,
2323
useColorModeValue,
2424
useDisclosure,
2525
} from "@chakra-ui/react"
@@ -36,9 +36,9 @@ export const useNav = () => {
3636
const { asPath } = useRouter()
3737
const { isOpen, onToggle } = useDisclosure()
3838
const { t } = useTranslation("common")
39+
const { theme, setTheme } = useTheme()
3940

4041
const colorToggleEvent = useColorModeValue("dark mode", "light mode") // This will be inverted as the state is changing
41-
const { toggleColorMode: chakraToggleColorMode } = useColorMode()
4242

4343
const linkSections: NavSections = {
4444
learn: {
@@ -477,7 +477,7 @@ export const useNav = () => {
477477
: ""
478478

479479
const toggleColorMode = () => {
480-
chakraToggleColorMode()
480+
setTheme(theme === "dark" ? "light" : "dark")
481481
trackCustomEvent({
482482
eventCategory: "nav bar",
483483
eventAction: "click",

src/pages/_app.tsx

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
import { useEffect } from "react"
2-
import { merge } from "lodash"
32
import { appWithTranslation } from "next-i18next"
4-
// ChakraProvider import updated as recommended on https://github.com/chakra-ui/chakra-ui/issues/4975#issuecomment-1174234230
5-
// to reduce bundle size. Should be reverted to "@chakra-ui/react" in case on theme issues
6-
import { ChakraProvider } from "@chakra-ui/provider"
3+
import { ThemeProvider as NextThemesProvider } from "next-themes"
74
import { init } from "@socialgouv/matomo-next"
85

9-
import customTheme from "@/@chakra-ui/theme"
10-
116
import { AppPropsWithLayout } from "@/lib/types"
127

8+
import ChakraThemeProvider from "@/components/ChakraThemeProvider"
9+
1310
import "@/styles/global.css"
1411
import "@/styles/main.css"
1512

16-
import { useLocaleDirection } from "@/hooks/useLocaleDirection"
1713
import { RootLayout } from "@/layouts/RootLayout"
1814
import { mono } from "@/lib/fonts"
1915

16+
export const STORAGE_KEY = "theme"
17+
2018
const App = ({ Component, pageProps }: AppPropsWithLayout) => {
2119
useEffect(() => {
2220
if (!process.env.IS_PREVIEW_DEPLOY) {
@@ -31,10 +29,6 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
3129
// Use the layout defined at the page level, if available
3230
const getLayout = Component.getLayout ?? ((page) => page)
3331

34-
const direction = useLocaleDirection()
35-
36-
const theme = merge(customTheme, { direction })
37-
3832
return (
3933
<>
4034
<style jsx global>
@@ -45,15 +39,23 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
4539
}
4640
`}
4741
</style>
48-
<ChakraProvider theme={theme}>
49-
<RootLayout
50-
contentIsOutdated={!!pageProps.frontmatter?.isOutdated}
51-
contentNotTranslated={pageProps.contentNotTranslated}
52-
lastDeployLocaleTimestamp={pageProps.lastDeployLocaleTimestamp}
53-
>
54-
{getLayout(<Component {...pageProps} />)}
55-
</RootLayout>
56-
</ChakraProvider>
42+
<NextThemesProvider
43+
attribute="class"
44+
defaultTheme="system"
45+
enableSystem
46+
disableTransitionOnChange
47+
storageKey={STORAGE_KEY}
48+
>
49+
<ChakraThemeProvider>
50+
<RootLayout
51+
contentIsOutdated={!!pageProps.frontmatter?.isOutdated}
52+
contentNotTranslated={pageProps.contentNotTranslated}
53+
lastDeployLocaleTimestamp={pageProps.lastDeployLocaleTimestamp}
54+
>
55+
{getLayout(<Component {...pageProps} />)}
56+
</RootLayout>
57+
</ChakraThemeProvider>
58+
</NextThemesProvider>
5759
</>
5860
)
5961
}

src/pages/_document.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import NextDocument, {
77
} from "next/document"
88
import { ColorModeScript } from "@chakra-ui/react"
99

10-
import theme from "@/@chakra-ui/theme"
11-
1210
import { Lang } from "@/lib/types"
1311

1412
import { isLangRightToLeft } from "@/lib/utils/translations"
1513

14+
import { STORAGE_KEY } from "./_app"
15+
1616
class Document extends NextDocument {
1717
static async getInitialProps(ctx: DocumentContext) {
1818
return await NextDocument.getInitialProps(ctx)
@@ -39,7 +39,11 @@ class Document extends NextDocument {
3939
/>
4040
</Head>
4141
<body>
42-
<ColorModeScript initialColorMode={theme.config.initialColorMode} />
42+
{/*
43+
Still needed to insert the chakra specific classname on the `body` (`chakra-ui-light` & `chakra-ui-dark`)
44+
and avoid color mode flashing
45+
*/}
46+
<ColorModeScript initialColorMode="system" storageKey={STORAGE_KEY} />
4347
<Main />
4448
<NextScript />
4549
</body>

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11019,6 +11019,11 @@ next-sitemap@^4.2.3:
1101911019
fast-glob "^3.2.12"
1102011020
minimist "^1.2.8"
1102111021

11022+
next-themes@^0.3.0:
11023+
version "0.3.0"
11024+
resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.3.0.tgz#b4d2a866137a67d42564b07f3a3e720e2ff3871a"
11025+
integrity sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==
11026+
1102211027
next@^14.2.3:
1102311028
version "14.2.3"
1102411029
resolved "https://registry.yarnpkg.com/next/-/next-14.2.3.tgz#f117dd5d5f20c307e7b8e4f9c1c97d961008925d"

0 commit comments

Comments
 (0)