雪山深处

利用 gatsby-plugin-use-dark-mode 来添加夜间模式功能

利用 gatsby-plugin-use-dark-mode 来添加夜间模式功能

2020 年 05 月 01 日 • 4 分钟

Gatsby
技术

一直以来,夜间模式都是人类眼睛的好朋友,但却常常被忽视。为了推动“夜间模式革命”,为人类带去黑暗,特写此文。

前言

介绍

看完众大佬们的教程后还是选择了直接上插件,毕竟可以省去很多时间和精力(真香)。下文会介绍如何使用 gatsby-plugin-use-dark-mode site preview image use-dark-mode site preview image 以及 Material-UI site preview image 的 Icon 和 Button 组件来制作一个顶级棒的夜间模式 ( •̀ ω •́ )y

各组件的作用

  • use-dark-mode:接受调用、提供主要的模式切换

  • gatsby-plugin-use-dark-mode:注入noflash.js来防止刷新时白屏

  • gatsby-plugin-material-ui:优化 Material UI 在 Gatsby 中的使用

  • Material UI(icons、core):提供漂亮的按键和图标

准备步骤

  1. 安装所需插件

    npm install gatsby-plugin-use-dark-mode use-dark-mode
    npm install gatsby-plugin-material-ui @mui/icons-material @mui/styled-engine @emotion/react @emotion/styled
  2. 在 gatsby-config.js 中启用gatsby-plugin-use-dark-modegatsby-plugin-material-ui

    module.exports = {
        plugins: [`gatsby-plugin-use-dark-mode`, `gatsby-plugin-material-ui`],
    };

编写一个 js 文件来处理点击事件

use-dark-mode 提供了一个简单的示例来告诉我们如何调用它,如下

import React from 'react';
import useDarkMode from 'use-dark-mode';

import Toggle from './Toggle';

const DarkModeToggle = () => {
    const darkMode = useDarkMode(false);

    return (
        <div>
            <button type="button" onClick={darkMode.disable}></button>
            <Toggle checked={darkMode.value} onChange={darkMode.toggle} />
            <button type="button" onClick={darkMode.enable}></button>
        </div>
    );
};

export default DarkModeToggle;

在这里我不想使用 react-toggle 而是使用 Material UI 的 Icons 和 Button 来显示,所以会有一些修改,主要思路是:

当我点击了右上角的 ☀ ,它会调用夜间模式的插件来实现模式地切换,同时把自己的 ☀ 设置为 ☾ 。这样一来,当我想切换回日间模式时点击的就是 ☾ 了,然后会发生的事同上。这样做能让页面更加的美观简洁(个人认为),也让代码变得更简单些。

将上述想法实现后,我得到了这个:

import React from 'react';
import useDarkMode from 'use-dark-mode';
import Sun from '@mui/icons-material/WbSunnyRounded';
import Moon from '@mui/icons-material/ModeNightRounded';
import IconButton from '@mui/material/IconButton';

export default function DarkModeButton() {
    const darkMode = useDarkMode(false);

    return (
        <IconButton type="button" onClick={darkMode.toggle}>
            {darkMode.value ? (
                <Moon style={{color: '#ffb74d'}} />
            ) : (
                <Sun style={{color: '#ff9800'}} />
            )}
        </IconButton>
    );
};

如上,一个简单的 Button 就出炉啦~当我们点击它时,它会调用darkMode.toggle来切换模式,同时按键的图标也会跟随darkMode.value来进行对应的切换。

修改 Layout.jsx

现在我们已经有了能调用夜间模式插件的 DarkModeButton.jsx,剩下要做的就是让每个页面都有一个按钮,和让 Material UI 的组件也能切换对应夜间模式的样式,方法是修改上层的 Layout.jsx。

import React from 'react';
import useDarkMode from 'use-dark-mode';
import {createTheme, ThemeProvider} from '@mui/material';
import DarkModeButton from './DarkModeButton';

export default function Layout({children}) {
    const darkMode = useDarkMode(false);

    const theme = React.useMemo(
        () =>
            createTheme({
                palette: {
                    mode: darkMode.value ? 'dark' : 'light',
                },
            }),
        [darkMode.value],
    );

    return (
        <ThemeProvider theme={theme}>
            <header style={{display: 'flex', justifyContent: 'space-between'}}>
                {header}
                <DarkMode mode={darkMode}  />
            </header>
            <main>{children}</main>
        </ThemeProvider>
    );
}

为了让 Layout 组件来管理 Material UI 的主题,我将 useDarkMode 放在 Layout 中了,所以 DarkModeButton 也要跟着修改:

import React from 'react';
- import useDarkMode from 'use-dark-mode';
import Sun from '@mui/icons-material/WbSunnyRounded';
import Moon from '@mui/icons-material/ModeNightRounded';
import IconButton from '@mui/material/IconButton';

- export default function DarkModeButton() {
+ export default function DarkModeButton({mode}) { 
-   const darkMode = useDarkMode(false);   

    return (
-       <IconButton type="button" onClick={darkMode.toggle}>
+       <IconButton type="button" onClick={mode.toggle}>
-           {darkMode.value ? (
+           {mode.value ? (
                <Moon style={{color: '#ffb74d'}} />
            ) : (
                <Sun style={{color: '#ff9800'}} />
            )}
        </IconButton>
    );
};

在全局 CSS 文件中添加相关样式

body.light-mode {
    background-color: #fff;
    color: #333;
    transition: background-color 0.3s ease;
}

body.dark-mode {
    background-color: #212121;
    color: #999;
    transition: background-color 0.3s ease;
}

.dark-mode blockquote {
    color: #999;
    border-left: 0.32813rem solid #999;
}

以上步骤结束后,你的网页应该能正常的切换日间和夜间模式了~

本文最后于2022 年 11 月 05 日更新,一些操作可能已经过时