为你的 Astro 应用添加暗黑模式。

暗黑模式

创建内联主题脚本

src/pages/index.astro

  1. ---
  2. import '../styles/globals.css'
  3. ---
  4. <script is:inline>
  5. const getThemePreference = () => {
  6. if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
  7. return localStorage.getItem('theme');
  8. }
  9. return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
  10. };
  11. const isDark = getThemePreference() === 'dark';
  12. document.documentElement.classList[isDark ? 'add' : 'remove']('dark');
  13. if (typeof localStorage !== 'undefined') {
  14. const observer = new MutationObserver(() => {
  15. const isDark = document.documentElement.classList.contains('dark');
  16. localStorage.setItem('theme', isDark ? 'dark' : 'light');
  17. });
  18. observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
  19. }
  20. </script>
  21. <html lang="en">
  22. <body>
  23. <h1>Astro</h1>
  24. </body>
  25. </html>

添加模式切换

src/components/ModeToggle.tsx

  1. import * as React from "react"
  2. import { Moon, Sun } from "lucide-react"
  3. import { Button } from "@/components/ui/button"
  4. import {
  5. DropdownMenu,
  6. DropdownMenuContent,
  7. DropdownMenuItem,
  8. DropdownMenuTrigger,
  9. } from "@/components/ui/dropdown-menu"
  10. export function ModeToggle() {
  11. const [theme, setThemeState] = React.useState<
  12. "theme-light" | "dark" | "system"
  13. >("theme-light")
  14. React.useEffect(() => {
  15. const isDarkMode = document.documentElement.classList.contains("dark")
  16. setThemeState(isDarkMode ? "dark" : "theme-light")
  17. }, [])
  18. React.useEffect(() => {
  19. const isDark =
  20. theme === "dark" ||
  21. (theme === "system" &&
  22. window.matchMedia("(prefers-color-scheme: dark)").matches)
  23. document.documentElement.classList[isDark ? "add" : "remove"]("dark")
  24. }, [theme])
  25. return (
  26. <DropdownMenu>
  27. <DropdownMenuTrigger asChild>
  28. <Button variant="outline" size="icon">
  29. <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
  30. <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
  31. <span className="sr-only">切换主题</span>
  32. </Button>
  33. </DropdownMenuTrigger>
  34. <DropdownMenuContent align="end">
  35. <DropdownMenuItem onClick={() => setThemeState("theme-light")}>
  36. 光明模式
  37. </DropdownMenuItem>
  38. <DropdownMenuItem onClick={() => setThemeState("dark")}>
  39. 暗黑模式
  40. </DropdownMenuItem>
  41. <DropdownMenuItem onClick={() => setThemeState("system")}>
  42. 系统模式
  43. </DropdownMenuItem>
  44. </DropdownMenuContent>
  45. </DropdownMenu>
  46. )
  47. }

显示模式切换

在你的站点上添加一个模式切换按钮,以在光明模式和暗黑模式之间切换。

src/pages/index.astro

  1. ---
  2. import '../styles/globals.css'
  3. import { ModeToggle } from '@/components/ModeToggle';
  4. ---
  5. <!-- 内联脚本 -->
  6. <html lang="en">
  7. <body>
  8. <h1>Astro</h1>
  9. <ModeToggle client:load />
  10. </body>
  11. </html>