为你的 Next.js 应用添加暗黑模式。

暗黑模式

安装 next-themes

首先安装 next-themes

pnpmnpmyarnbun

  1. pnpm add next-themes

创建主题提供者

components/theme-provider.tsx

  1. "use client"
  2. import * as React from "react"
  3. import { ThemeProvider as NextThemesProvider } from "next-themes"
  4. export function ThemeProvider({
  5. children,
  6. ...props
  7. }: React.ComponentProps<typeof NextThemesProvider>) {
  8. return <NextThemesProvider {...props}>{children}</NextThemesProvider>
  9. }

包装根布局

ThemeProvider 添加到你的根布局中。

app/layout.tsx

  1. import { ThemeProvider } from "@/components/theme-provider"
  2. export default function RootLayout({ children }: RootLayoutProps) {
  3. return (
  4. <>
  5. <html lang="en" suppressHydrationWarning>
  6. <head />
  7. <body>
  8. <ThemeProvider
  9. attribute="class"
  10. defaultTheme="system"
  11. enableSystem
  12. disableTransitionOnChange
  13. >
  14. {children}
  15. </ThemeProvider>
  16. </body>
  17. </html>
  18. </>
  19. )
  20. }

添加模式切换

在你的站点上放置一个模式切换按钮,用于在亮色模式和暗色模式之间切换。

PreviewCode

  1. "use client"
  2. import * as React from "react"
  3. import { Moon, Sun } from "lucide-react"
  4. import { useTheme } from "next-themes"
  5. import { Button } from "@/components/ui/button"
  6. import {
  7. DropdownMenu,
  8. DropdownMenuContent,
  9. DropdownMenuItem,
  10. DropdownMenuTrigger,
  11. } from "@/components/ui/dropdown-menu"
  12. export function ModeToggle() {
  13. const { setTheme } = useTheme()
  14. return (
  15. <DropdownMenu>
  16. <DropdownMenuTrigger asChild>
  17. <Button variant="outline" size="icon">
  18. <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
  19. <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
  20. <span className="sr-only">Toggle theme</span>
  21. </Button>
  22. </DropdownMenuTrigger>
  23. <DropdownMenuContent align="end">
  24. <DropdownMenuItem onClick={() => setTheme("light")}>
  25. Light
  26. </DropdownMenuItem>
  27. <DropdownMenuItem onClick={() => setTheme("dark")}>
  28. Dark
  29. </DropdownMenuItem>
  30. <DropdownMenuItem onClick={() => setTheme("system")}>
  31. System
  32. </DropdownMenuItem>
  33. </DropdownMenuContent>
  34. </DropdownMenu>
  35. )
  36. }