ThemeProvider
ThemeProvider는 Poodle UI의 핵심 컴포넌트로, 앱 전체에 브랜드 테마를 주입하고 Light/Dark 모드를 관리해요.
기본 사용법
앱의 최상위에서 ThemeProvider로 감싰다면 모든 자식 컴포넌트에 테마가 적용되어요.
import { ThemeProvider, defineTheme } from '@poodle-kit/ui/theme';
const myTheme = defineTheme({
colors: {
primary: {
DEFAULT: '#10b981',
foreground: '#ffffff',
}
}
});
function App() {
return (
<ThemeProvider config={myTheme}>
<YourApp />
</ThemeProvider>
);
}Props
config
- 타입:
ThemeConfig - 기본값:
undefined - 설명: Light 모드에 적용될 테마 설정
<ThemeProvider config={myLightTheme}>
<App />
</ThemeProvider>darkConfig
- 타입:
ThemeConfig - 기본값:
undefined - 설명: Dark 모드에 적용될 테마 설정
<ThemeProvider
config={myLightTheme}
darkConfig={myDarkTheme}
>
<App />
</ThemeProvider>defaultTheme
- 타입:
'light' | 'dark' | 'system' - 기본값:
'system' - 설명: 앱 초기 로드 시 사용할 테마
<ThemeProvider
defaultTheme="dark" // 다크 모드로 시작
config={myLightTheme}
darkConfig={myDarkTheme}
>
<App />
</ThemeProvider>storageKey
- 타입:
string - 기본값:
'poodle-ui-theme' - 설명: LocalStorage에 저장될 키 이름
<ThemeProvider
storageKey="my-app-theme" // 커스텀 storage key
config={myTheme}
>
<App />
</ThemeProvider>enableColorSchemeSync
- 타입:
boolean - 기본값:
true - 설명: 시스템 테마 변경 자동 감지 여부
<ThemeProvider
enableColorSchemeSync={false} // 시스템 테마 동기화 비활성화
config={myTheme}
>
<App />
</ThemeProvider>프레임워크별 설정
Next.js App Router
// app/layout.tsx
import { ThemeProvider, defineTheme } from '@poodle-kit/ui/theme';
import '@poodle-kit/ui/styles.css';
const theme = defineTheme({ /* ... */ });
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ko" suppressHydrationWarning>
<body>
<ThemeProvider config={theme} darkConfig={darkTheme}>
{children}
</ThemeProvider>
</body>
</html>
);
}주의: html 태그에 suppressHydrationWarning을 추가해야 해요. ThemeProvider가 클라이언트에서 다크 모드 클래스를 주입하기 때문이에요.
Next.js Pages Router
// pages/_app.tsx
import { ThemeProvider, defineTheme } from '@poodle-kit/ui/theme';
import '@poodle-kit/ui/styles.css';
import type { AppProps } from 'next/app';
const theme = defineTheme({ /* ... */ });
export default function App({ Component, pageProps }: AppProps) {
return (
<ThemeProvider config={theme} darkConfig={darkTheme}>
<Component {...pageProps} />
</ThemeProvider>
);
}Vite
// src/main.tsx
import { ThemeProvider, defineTheme } from '@poodle-kit/ui/theme';
import '@poodle-kit/ui/styles.css';
import ReactDOM from 'react-dom/client';
import App from './App';
const theme = defineTheme({ /* ... */ });
ReactDOM.createRoot(document.getElementById('root')!).render(
<ThemeProvider config={theme} darkConfig={darkTheme}>
<App />
</ThemeProvider>
);Remix
// app/root.tsx
import { ThemeProvider, defineTheme } from '@poodle-kit/ui/theme';
import '@poodle-kit/ui/styles.css';
const theme = defineTheme({ /* ... */ });
export default function App() {
return (
<html lang="ko">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<ThemeProvider config={theme} darkConfig={darkTheme}>
<Outlet />
</ThemeProvider>
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}useTheme Hook
테마를 동적으로 변경하려면 useTheme 훅을 사용하면 되어요.
import { useTheme } from '@poodle-kit/ui/theme';
function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
현재: {theme} 모드
</button>
);
}useTheme 반환값
{
theme: 'light' | 'dark' | 'system', // 현재 테마
setTheme: (theme: Theme) => void, // 테마 변경 함수
}고급 사용법
다중 브랜드 테마
여러 브랜드를 지원하는 앱의 경우 아래와 같이 구성할 수 있어요:
// themes/brand-a.ts
export const brandATheme = defineTheme({
colors: {
primary: { DEFAULT: '#10b981', foreground: '#ffffff' }
}
});
// themes/brand-b.ts
export const brandBTheme = defineTheme({
colors: {
primary: { DEFAULT: '#3b82f6', foreground: '#ffffff' }
}
});
// App.tsx
function App() {
const [currentBrand, setCurrentBrand] = useState('a');
return (
<ThemeProvider
config={currentBrand === 'a' ? brandATheme : brandBTheme}
>
<YourApp />
</ThemeProvider>
);
}테마 전환 애니메이션
CSS transitions를 사용하여 부드러운 테마 전환을 구현할 수 있어요.
/* globals.css */
* {
transition: background-color 0.3s ease, color 0.3s ease;
}문제 해결
ThemeProvider를 찾을 수 없음
Error: Cannot find module '@poodle-kit/ui/theme'해결: package.json의 exports를 확인해보세요.
{
"exports": {
"./theme": "./dist/theme/index.js"
}
}테마가 적용되지 않음
-
CSS import 확인
import '@poodle-kit/ui/styles.css'; -
ThemeProvider 위치 확인
- 앱 최상위에 위치해야 해요
- 모든 컴포넌트를 감싸야 해요
-
Tailwind 설정 확인
// tailwind.config.js module.exports = { darkMode: 'class', // 중요! }
Next.js hydration 에러
Warning: Prop `className` did not match해결: html 태그에 suppressHydrationWarning을 추가하면 되어요.
<html lang="ko" suppressHydrationWarning>