이 사이트는 shadcn-svelte 공식 문서의 한국어 번역입니다.
6.9k

Astro

Previous Next

Astro 사이트에 다크 모드 추가하기.

일반 Svelte와 마찬가지로, 다크 모드 전환을 지원하기 위해 Tailwind CSS의 class 전략을 사용합니다. 자세한 내용은 Tailwind CSS 문서를 참조하세요.

html 엘리먼트에 dark 클래스를 추가하는 방법은 자유롭게 선택할 수 있습니다. 이 가이드에서는 mode-watcher를 사용하여 다크 모드 전환을 활성화하는 방법을 살펴보겠습니다.

사용법

인라인 테마 스크립트 생성

이 스크립트는 localStorage에 다크 모드 값을 저장하고 추적하며, FUOC를 방지하는 역할을 합니다.

src/pages/index.astro
---
import "../styles/global.css";
---
 
<script is:inline>
  const isBrowser = typeof localStorage !== 'undefined';
  const getThemePreference = () => {
    if (isBrowser && localStorage.getItem('theme')) {
      return localStorage.getItem('theme');
    }
    return window.matchMedia('(prefers-color-scheme: dark)').matches
      ? 'dark' : 'light';
  };
  const isDark = getThemePreference() === 'dark';
  document.documentElement.classList[isDark ? 'add' : 'remove']('dark');
 
  if (isBrowser) {
    const observer = new MutationObserver(() => {
      const isDark = document.documentElement.classList.contains('dark');
      localStorage.setItem('theme', isDark ? 'dark' : 'light');
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });
  }
</script>
 
<html lang="en">
	<body>
      <h1>Astro</h1>
	</body>
</html>
</script>

mode-watcher 설치

pnpm i mode-watcher@0.5.1

ModeWatcher 컴포넌트 추가

ModeWatcher 컴포넌트를 import하고 client:load 디렉티브와 함께 페이지에서 사용하세요:

src/pages/index.astro
---
import "../styles/global.css";
import { ModeWatcher } from "mode-watcher";
---
 
<!-- inline-script -->
<html lang="en">
	<body>
      <h1>Astro</h1>
      <ModeWatcher client:load />
	</body>
</html>

모드 토글 생성

사이트에서 라이트 모드와 다크 모드를 전환할 수 있는 모드 토글을 생성하세요:

라이트 스위치

<script lang="ts">
  import SunIcon from "@lucide/svelte/icons/sun";
  import MoonIcon from "@lucide/svelte/icons/moon";
 
  import { toggleMode } from "mode-watcher";
  import { Button } from "$lib/components/ui/button/index.js";
</script>
 
<Button onclick={toggleMode} variant="outline" size="icon">
  <SunIcon
    class="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 !transition-all dark:scale-0 dark:-rotate-90"
  />
  <MoonIcon
    class="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 !transition-all dark:scale-100 dark:rotate-0"
  />
  <span class="sr-only">Toggle theme</span>
</Button>

드롭다운 메뉴

<script lang="ts">
  import SunIcon from "@lucide/svelte/icons/sun";
  import MoonIcon from "@lucide/svelte/icons/moon";
 
  import { resetMode, setMode } from "mode-watcher";
  import * as DropdownMenu from "$lib/components/ui/dropdown-menu/index.js";
  import { buttonVariants } from "$lib/components/ui/button/index.js";
</script>
 
<DropdownMenu.Root>
  <DropdownMenu.Trigger
    class={buttonVariants({ variant: "outline", size: "icon" })}
  >
    <SunIcon
      class="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 !transition-all dark:scale-0 dark:-rotate-90"
    />
    <MoonIcon
      class="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 !transition-all dark:scale-100 dark:rotate-0"
    />
    <span class="sr-only">Toggle theme</span>
  </DropdownMenu.Trigger>
  <DropdownMenu.Content align="end">
    <DropdownMenu.Item onclick={() => setMode("light")}>Light</DropdownMenu.Item
    >
    <DropdownMenu.Item onclick={() => setMode("dark")}>Dark</DropdownMenu.Item>
    <DropdownMenu.Item onclick={() => resetMode()}>System</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu.Root>

페이지에 모드 토글 추가

모드 토글을 페이지에 추가하세요 (client:load 디렉티브와 함께):

src/pages/index.astro
---
import "../styles/global.css";
import { ModeWatcher } from "mode-watcher";
import ModeToggle from "$lib/components/mode-toggle.svelte";
---
 
<!-- inline-script -->
<html lang="en">
	<body>
      <h1>Astro</h1>
      <ModeWatcher client:load />
      <ModeToggle client:load />
	</body>
</html>