다크 모드
KRDS 고대비 모드를 적용하는 방법과 색상 토큰 사용 규칙입니다.
KRDS는 다크 모드를 고대비 모드로 정의합니다. 토큰 스타일시트(app/krds.css)에 다크 모드 값이 포함되어 있으므로, 컴포넌트를 설치했다면 <html>에 .dark 클래스를 토글하는 것으로 적용됩니다.
동작 방식
krds.css는 원시 색상 팔레트(프리미티브)는 그대로 두고 역할 토큰(시맨틱)만 .dark에서 리매핑합니다.
:root {
--krds-foreground-primary: var(--krds-color-primary-60);
--krds-surface: var(--krds-color-gray-0);
}
.dark {
--krds-foreground-primary: var(--krds-color-primary-20);
--krds-surface: var(--krds-color-gray-100);
}컴포넌트는 bg-krds-surface, text-krds-foreground-primary 같은 시맨틱 클래스를 사용하므로 클래스 토글만으로 전체 색상이 일관되게 전환됩니다.
next-themes 설정
attribute="class"로 설정하면 next-themes가 <html>에 .dark 클래스를 관리합니다. suppressHydrationWarning은 next-themes가 서버 렌더 후 클래스를 조정할 때 발생하는 하이드레이션 경고를 방지합니다.
import { ThemeProvider } from "next-themes"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko" suppressHydrationWarning>
<body>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</body>
</html>
)
}토글 버튼
"use client"
import { useTheme } from "next-themes"
import { Button } from "@/components/ui/krds/(action)/button"
export function ModeToggle() {
const { resolvedTheme, setTheme } = useTheme()
return (
<Button variant="text" size="sm" onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}>
{resolvedTheme === "dark" ? "라이트 모드" : "다크 모드"}
</Button>
)
}색상 토큰 사용 규칙
일부 영역만 색이 전환되지 않는다면 대부분 색상 하드코딩이 원인입니다. 직접 작성하는 코드에서 두 가지 규칙을 지킵니다.
- 고정 색을 사용하지 않습니다.
bg-white,text-[#333]은 테마를 따르지 않습니다.bg-krds-surface,text-krds-foreground같은 시맨틱 토큰 클래스를 사용합니다. - 프리미티브보다 시맨틱을 우선합니다.
bg-krds-gray-0같은 프리미티브 토큰도 다크 모드에서 값이 바뀌지 않습니다. 해당 위치의 역할에 맞는 시맨틱 토큰(surface,foreground,border계열)을 사용합니다.