테마
프로젝트 전역 스타일과 컴포넌트 토큰을 조정하고 다크 모드를 적용하는 방법입니다.
기본 원칙
테마는 krds-theme라는 별도의 레지스트리 아이템(registry:theme)으로 관리됩니다. 컴포넌트를 하나라도 설치하면 registryDependencies를 통해 자동으로 함께 설치되며, CLI가 프로젝트 CSS 파일에 색상·타이포그래피·포커스 링 토큰을 직접 병합합니다. 컴포넌트 자체는 프로젝트 안으로 복사된 소스를 기준으로 수정합니다.
- Radix 기반 컴포넌트 구조와 호환
- 테마 토큰은 설치 시 자동 병합 — 수동 CSS 편집 불필요
- 컴포넌트 소스에서 직접 수정 가능
CSS 변수
설치 대상 프로젝트가 Tailwind CSS v4(@theme inline 지원)를 사용하도록 먼저 준비하세요.
pnpm dlx shadcn@latest init이후 컴포넌트를 설치하면 krds-theme가 --krds-color-*, --krds-foreground*, --krds-surface*, --krds-border*, --text-krds-* 등 KRDS 전용 CSS 변수를 프로젝트 CSS의 @theme inline / :root / .dark 블록에 자동으로 추가합니다. shadcn/ui의 기본 토큰(background, primary, ring 등)과는 별개의 이름공간이므로 서로 충돌하지 않습니다. 프로젝트별 색상 조정이 필요하면 해당 CSS 변수 값을 직접 변경하세요.
컴포넌트 수정
레지스트리로 설치한 컴포넌트는 패키지 내부에 숨겨지지 않고 프로젝트 파일로 복사됩니다. 디자인 요구사항이 생기면 설치된 components/ui/* 파일을 기준으로 직접 수정하세요.
다크 모드
KRDS는 다크 모드를 고대비 모드로 정의합니다. krds-theme 설치 시 다크 모드 값이 프로젝트 CSS의 .dark 블록에 함께 병합되므로, <html>에 .dark 클래스를 토글하는 것만으로 적용됩니다.
동작 방식
원시 색상 팔레트(프리미티브)는 그대로 두고 역할 토큰(시맨틱)만 .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 설정
pnpm add next-themesattribute="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/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계열)을 사용합니다.