Getting Started
Theming
라이트, 다크, 시스템 테마를 자동으로 지원하는 Vapor UI 테마 시스템을 설정하세요.Vapor UI는 라이트 모드, 다크 모드, 시스템 동기화를 자동으로 지원합니다. ThemeProvider 하나로 완전한 테마 관리 시스템을 구축할 수 있습니다.
빠른 설정
패키지 설치
npm install @vapor-ui/core@betaThemeProvider 설정
애플리케이션 최상위를 ThemeProvider로 감싸면 테마 시스템이 활성화됩니다:
import { ThemeProvider } from '@vapor-ui/core';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko" suppressHydrationWarning>
<body>
<ThemeProvider defaultTheme="system">{children}</ThemeProvider>
</body>
</html>
);
}SSR 팁:
suppressHydrationWarning을<html>태그에 추가하면 서버-클라이언트 테마 차이로 인한 하이드레이션 경고를 방지할 수 있습니다.
테마 제어하기
useTheme 훅으로 테마를 읽고 변경할 수 있습니다. 다음 예제는 테마 토글 버튼 구현 방법입니다:
'use client';
import { Button } from '@vapor-ui/components/ui/button';
import { useTheme } from '@vapor-ui/core';
export function ThemeToggle() {
const { resolvedTheme, setTheme, mounted } = useTheme();
// SSR 환경에서 hydration 완료 전까지 로딩 상태 표시
if (!mounted) {
return null;
}
return (
<Button
variant="ghost"
onClick={() => setTheme(resolvedTheme === 'light' ? 'dark' : 'light')}
>
{resolvedTheme === 'light' ? 'Dark' : 'Light'}
</Button>
);
}useTheme 훅 레퍼런스
테마 관리에 필요한 모든 기능을 제공합니다:
| Key | Type | Description |
|---|---|---|
| theme | 'light' | 'dark' | 'system' | undefined | 현재 설정된 테마. SSR 환경에서 mounted가 false일 때는 undefined. |
| setTheme | (theme: 'light' | 'dark' | 'system' | ((prev: Theme) => Theme)) => void | 테마를 변경하는 함수. 함수형 업데이트도 지원하며 localStorage에 자동 저장됩니다. |
| themes | ('light' | 'dark' | 'system')[] | 사용 가능한 테마 목록. 항상 ['light', 'dark', 'system']을 포함합니다. |
| resolvedTheme | 'light' | 'dark' | undefined | 실제로 적용된 테마. theme가 'system'일 때 현재 시스템 테마를 반영합니다. |
| systemTheme | 'light' | 'dark' | undefined | 현재 사용자의 시스템 테마. theme가 'system'일 때만 제공됩니다. |
| forcedTheme | 'light' | 'dark' | 'system' | undefined | 강제로 적용된 테마. 설정되지 않았을 때는 undefined. |
| resetTheme | () => void | 테마 설정을 기본값으로 초기화하고 localStorage에서 저장된 값을 제거합니다. |
| mounted | boolean | ThemeProvider가 클라이언트에서 마운트되었는지 여부. SSR 환경에서 hydration 이슈 방지를 위해 사용. |
ThemeProvider 설정 옵션
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultTheme | 'light' | 'dark' | 'system' | 'system' | 테마 동작을 결정합니다. 'light', 'dark'는 고정 테마, 'system'은 시스템 테마에 자동 동기화됩니다. |
| storageKey | string | 'vapor-ui-theme' | localStorage에 테마를 저장할 때 사용될 키. |
| forcedTheme` | 'light' | 'dark' | 'system' | undefined | 특정 테마를 강제로 적용합니다. 이 값이 설정되면 다른 모든 테마 관련 설정을 무시합니다. |
| disableTransitionOnChange | boolean | false | true일 경우, 테마 변경 시 발생하는 CSS 트랜지션을 비활성화합니다. |
| enableColorScheme | boolean | true | true일 경우, color-scheme CSS 속성을 자동으로 설정하여 브라우저 UI(스크롤바 등)의 테마를 조정합니다. |
| nonce | string | undefined | undefined | CSP(Content Security Policy) nonce 값. 보안 정책이 적용된 환경에서 사용. |
부분 테마 적용 (ThemeScope)
특정 영역에만 다른 테마를 적용하고 싶을 때 ThemeScope를 사용합니다:
import { Card } from '@vapor-ui/components/ui/card';
import { ThemeScope } from '@vapor-ui/core';
export function ThemeScopeExample() {
return (
<div>
<Card>전역 테마가 적용된 카드</Card>
<ThemeScope forcedTheme="dark">
<Card>다크 테마가 강제 적용된 카드</Card>
</ThemeScope>
<ThemeScope forcedTheme="light">
<Card>라이트 테마가 강제 적용된 카드</Card>
</ThemeScope>
</div>
);
}Portal 컴포넌트와 함께 사용
Dialog, Popover 같은 Portal 컴포넌트가 ThemeScope의 테마를 상속받으려면 컨테이너를 지정하세요:
<ThemeScope forcedTheme="dark">
<section ref={sectionRef}>
{' '}
{/* 어떤 요소든 가능 */}
<Dialog.Content portalProps={{ container: sectionRef.current }}>
{/* 이 Portal은 다크 테마를 상속받음 */}
</Dialog.Content>
</section>
</ThemeScope>ThemeScope 옵션
| Prop | Type | Description |
|---|---|---|
| forcedTheme | 'light' | 'dark' | 해당 영역에 강제로 적용할 테마 |
| children | React.ReactNode | 테마가 적용될 자식 컴포넌트들 |
| style | CSSProperties | undefined | 추가 스타일 (colorScheme 자동 설정) |
고급 기능
SSR 자동 처리
서버-클라이언트 테마 차이로 인한 hydration 오류를 자동으로 방지합니다:
mounted상태 추적: 클라이언트 마운트 완료 여부 확인- 안전한 기본값: 마운트 전까지 충돌 없는 값 사용
- 자동 동기화: 마운트 완료 후 실제 테마로 업데이트
테마 동작 모드
고정 테마 ('light' 또는 'dark'):
- 지정된 테마로 고정
- 시스템 테마 변경 무시
- 사용자가 수동으로 변경 가능
시스템 동기화 ('system'):
- 운영체제 테마 설정 자동 감지
prefers-color-scheme미디어 쿼리로 실시간 추적- 시스템 변경 시 자동 업데이트
우선순위 시스템
forcedTheme- 강제 테마 (최우선)localStorage- 사용자 선택 (사용자 존중)defaultTheme- 기본 설정 (초기값)
다중 탭 동기화
여러 브라우저 탭 간 테마 설정을 자동으로 동기화합니다. 한 탭에서 테마를 변경하면 같은 도메인의 다른 탭들도 즉시 업데이트됩니다.
TypeScript 지원
import type { ThemeConfig, ThemeScopeProps, UseThemeProps } from '@vapor-ui/core';
// 시스템 테마에 자동 동기화
const systemConfig: ThemeConfig = {
defaultTheme: 'system',
};
// 라이트 테마로 고정
const lightConfig: ThemeConfig = {
defaultTheme: 'light',
};
const MyComponent = () => {
const themeData: UseThemeProps = useTheme();
// ...
};