Themes
DDS 테마 시스템은 라이트/다크 모드를 손쉽게 관리합니다.
Installation
Terminal
$ pnpm add @b1nd/dodam-design-system/themes
Setup
Next.js
ThemeSetter컴포넌트를<head>내에 배치하여 깜빡임 없이 초기 테마를 적용합니다.suppressHydrationWarning속성을<html>태그에 추가하여 hydration 경고를 방지합니다.
tsx
// app/layout.tsximport { ThemeSetter } from "@b1nd/dodam-design-system/next";import { PropsWithChildren } from "react";export default function RootLayout({ children }: PropsWithChildren) {return (<html lang="ko" suppressHydrationWarning><head><ThemeSetter /></head><body>{children}</body></html>);}
Vite + React
- 아래를 index.html의 head태그 내부 가장 위에 복사/붙혀넣기 해주세요.
html
<head><script>(function () {try {const stored = localStorage.getItem("dds-theme");const system = window.matchMedia("(prefers-color-scheme: dark)").matches? "dark": "light";const theme =stored === "dark" || stored === "light" ? stored : system;document.documentElement.dataset.theme = theme;const style = document.createElement("style");style.textContent ="*, *::before, *::after { transition: none !important; }";document.head.appendChild(style);window.addEventListener("DOMContentLoaded", () => {requestAnimationFrame(() => {requestAnimationFrame(() => {style.remove();});});});} catch {}})();</script></head>
API Reference
Theme Type
tsx
type Theme = "light" | "dark";
Functions
| Function | Return | Description |
|---|---|---|
initTheme() | Theme | 저장된 테마 또는 시스템 테마를 적용하고 반환 |
getCurrentTheme() | Theme | null | 현재 적용된 테마 반환 |
applyTheme(theme) | void | 테마를 적용하고 localStorage에 저장 |
toggleTheme() | void | 라이트/다크 테마 토글 |
getSystemTheme() | Theme | 시스템 테마 반환 |
getStoredTheme() | Theme | null | localStorage에 저장된 테마 반환 |
resolveInitialTheme() | Theme | 저장된 테마 또는 시스템 테마 반환 |
Hooks
useTheme
현재 테마를 반환하는 React Hook입니다.
tsx
import { useTheme } from "@b1nd/dodam-design-system/themes";function Component() {const theme = useTheme(); // "light" | "dark"return <div>Current theme: {theme}</div>;}
Examples
테마 토글 버튼
tsx
"use client";import { useTheme, toggleTheme } from "@b1nd/dodam-design-system/themes";import { Sun, Moon } from "lucide-react";function ThemeToggle() {const theme = useTheme();return (<button onClick={toggleTheme}>{theme === "light" ? <Moon /> : <Sun />}</button>);}
현재 테마:
light테마별 스타일링
tsx
import { useTheme } from "@b1nd/dodam-design-system/themes";function ThemedCard() {const theme = useTheme();return (<divstyle={{backgroundColor: theme === "light" ? "#FFFFFF" : "#232424",color: theme === "light" ? "#0F0F10" : "#F5F5F5",}}>Theme-aware content</div>);}
이 카드는 현재 테마에 따라 색상이 변경됩니다.
특정 테마 적용
tsx
import { applyTheme } from "@b1nd/dodam-design-system/themes";function ThemeSelector() {return (<div><button onClick={() => applyTheme("light")}>Light</button><button onClick={() => applyTheme("dark")}>Dark</button></div>);}
How It Works
테마 적용 흐름
- 초기화:
ThemeSetter또는init-theme.iife.js가 localStorage와 시스템 설정을 확인 - 적용:
document.documentElement.dataset.theme에 테마 값 설정 - CSS 변수:
[data-theme="dark"]선택자로 스타일 적용 (data-theme이 없다면 :root 적용) - 저장: 테마 변경 시 localStorage에 저장되어 새로고침 후에도 유지
CSS 변수 구조
css
:root {--dds-color-text-primary: #0F0F10;--dds-color-background-default: #F5F5F5;/* ... */}[data-theme="dark"] {--dds-color-text-primary: #F5F5F5;--dds-color-background-default: #191A1A;/* ... */}
Flash 방지
Next.js에서 ThemeSetter는 <head> 내부에서 동기적으로 실행되어 hydration 전에 테마를 적용합니다. 이로 인해 페이지 로드 시 깜빡임(flash)이 발생하지 않습니다.
tsx
// ThemeSetter가 생성하는 스크립트(function() {try {var s = localStorage.getItem("dds-theme");var m = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";var t = s === "dark" || s === "light" ? s : m;document.documentElement.dataset.theme = t;} catch(e) {}})();