明亮黑暗主题

明暗主题就是整体颜色是亮色或暗色的主题, 根据用户使用场景(比如白天或夜晚), 提供切换选项来切换系统整体颜色, 让用户视觉上拥有更舒适的体验

git仓库

本章是nextjs入门课程系列的一部分, 查看以下git仓库, 并切换到extra1分支, 可查看本章代码

安装next-themes

1
pnpm install next-themes

配置tailwind主题支持

1
2
3
4
5
6
7
8
9
// tailwind.config.ts
import type {Config} from "tailwindcss";

const config: Config = {
// 通过类名的方式配置mode
darkMode: ['selector', '.dark'],
/// ...
};
export default config;

在layout.tsx中添加provider

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// app/layout.tsx
///
import {ThemeProvider} from "next-themes";

/// ...

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<body className={inter.className}>
{/*提供主题状态*/}
<ThemeProvider>
<Navbar/>
{children}
<Footbar/>
</ThemeProvider>
</body>
</html>
);
}

在navbar中添加切换按钮

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// components/navbar.tsx
"use client";
import {useTheme} from "next-themes";

export default function Navbar() {
// 获取当前主题和设置主题的方法
const {setTheme, resolvedTheme} = useTheme();

return (
<nav className={'bg-green-200 border-b border-b-gray-300 sticky w-full h-20 flex items-center'}>
<div className={'flex-1'}></div>
{resolvedTheme !== 'dark' ?
// 切换颜色主题的按钮
<img className={'size-10'}
onClick={() => setTheme('dark')}
src="https://www.svgrepo.com/show/489517/mode-dark.svg"
alt="to dark theme mode"/> :
<img className={'size-10'}
onClick={() => setTheme('light')}
src="https://www.svgrepo.com/show/489519/mode-light.svg"
alt="to light theme mode"/>
}
</nav>
)
}

关于”use client”: 这是启用了客户端的功能, 比如js交互/浏览器storage/cookie等

查看效果:

明亮模式
明亮模式
黑暗模式
黑暗模式

针对黑暗模式添加样式

你是否发现了, 暗黑模式下文字样式改变了, 而有些我们已经指定了样式(className中)的没有改变.

我们可以使用dark:来配置黑暗模式下的样式

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// components/navbar.tsx
"use client";
import {useTheme} from "next-themes";

export default function Navbar() {
/// ...

return (
<nav className={
`bg-green-200 dark:bg-green-800 ...`
}>
{/*...*/}
</nav>
)
}

// components/footbar.tsx

export default function Footbar() {

return (
<footer
className={
`bg-gray-200 dark:bg-gray-800 ...`
}>
footbar
</footer>
)
}
jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// app/blog/[slug]/page.tsx

// 服务端组件可以使用async
export default async function BlogPage({
params,
searchParams,
}: {
params: { slug: string } // 接收url参数: (/blog/[slug] -> slug)
searchParams: {}
}) {
/// ...

return (
// flex flex-row justify-center -> 内容居中
<div className={'w-screen flex flex-row justify-center'}>
{/*
prose让文本中的标题有对应的样式
dark:prose-invert是让prose适配黑暗主题
*/}
<div className={`prose dark:prose-invert`}
dangerouslySetInnerHTML={{__html: html}}>
</div>
</div>
)
}

效果:

结束

谢谢观看!


本站总访问量