DEV Community

panfan
panfan

Posted on • Originally published at manon.icu on

Next.js - Switch Theme Mode

前置

【上一篇】完成了使用 Next.js 构建 blog。

注意

主题切换基于chakra-uitailwindcss(可选),chakra-ui 和 tailwind.css 都内置支持颜色模式

chakra-ui 将颜色模式变量值存储在localstorage中,以确保持久化

详细文档参考Color Mode

pnpm install react-icons
Enter fullscreen mode Exit fullscreen mode

设置

新增utils/theme.ts

import {extendTheme, type ThemeConfig} from '@chakra-ui/react'

const theme = extendTheme({
  config: {
    initialColorMode: 'system',
    useSystemColorMode: true
  } as ThemeConfig,
  fonts: {
    heading: `'Dosis', sans-serif`
  }
})

export default theme
Enter fullscreen mode Exit fullscreen mode

修改_document.js

// pages/_document.js

import {ColorModeScript} from '@chakra-ui/react'
import NextDocument, {Html, Head, Main, NextScript} from 'next/document'
import theme from './theme'

export default class Document extends NextDocument {
  render() {
    return (
      <Html lang="en">
        <Head />
        <body>
          {/* 👇 Here's the script */}
          <ColorModeScript initialColorMode={theme.config.initialColorMode} />
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

新增components/DarkModeSwitch/index.tsx

import {useColorMode, Box} from '@chakra-ui/react'
import {BsMoonFill, BsFillSunFill} from 'react-icons/bs'

const DarkModeSwitch = () => {
  const {colorMode, toggleColorMode} = useColorMode()
  return (
    <Box
      as="div"
      position="absolute"
      top={4}
      right={4}
      zIndex={9999}
      onClick={toggleColorMode}
    >
      {colorMode === 'light' ? (
        <BsMoonFill size={18} />
      ) : (
        <BsFillSunFill size={18} />
      )}
    </Box>
  )
}

export default DarkModeSwitch
Enter fullscreen mode Exit fullscreen mode

修改pages/_app.tsx

import dynamic from 'next/dynamic'
import Head from 'next/head'
import React from 'react'
import {ChakraProvider} from '@chakra-ui/react'
import theme from 'utils/theme'

// 新增
const DarkModeSwitch = dynamic(() => import('components/DarkModeSwitch'), {
  ssr: false
})

const App = ({Component, pageProps, router}) => {
  const {route} = router
  const url = `https://manon.icu${route}`

  return (
    <>
      <Head>
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1.0, maximum-scale=5"
        />
        <meta httpEquiv="X-UA-Compatible" content="ie=edge" />
        <meta name="description" content="Manon.icu,homepage" />
        <title>Manon.icu | Home</title>
      </Head>
      <ChakraProvider theme={theme}>
        {/* 新增 */}
        <DarkModeSwitch />
        <Component {...pageProps} canonical={url} key={url} />
      </ChakraProvider>
    </>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Source Code

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more