diff --git a/components/__tests__/theme-provider.test.tsx b/components/__tests__/theme-provider.test.tsx
new file mode 100644
index 0000000..6a6625a
--- /dev/null
+++ b/components/__tests__/theme-provider.test.tsx
@@ -0,0 +1,51 @@
+import React from 'react'
+import { render, waitFor, cleanup } from '@testing-library/react'
+
+jest.mock('next-themes', () => {
+ return {
+ __esModule: true,
+ ThemeProvider: ({ children }: any) =>
{children}
,
+ useTheme: jest.fn(),
+ }
+})
+
+import { ThemeProvider } from '../theme-provider'
+import { useTheme } from 'next-themes'
+
+afterEach(() => {
+ cleanup()
+ // remove any css vars we set
+ ;['bg', 'text', 'muted', 'accent'].forEach((k) =>
+ document.documentElement.style.removeProperty(`--${k}`),
+ )
+})
+
+test('applies dark CSS custom properties when theme is dark', async () => {
+ ;(useTheme as jest.Mock).mockReturnValue({ resolvedTheme: 'dark' })
+
+ render(
+
+ child
+ ,
+ )
+
+ await waitFor(() => {
+ expect(getComputedStyle(document.documentElement).getPropertyValue('--bg').trim()).toBe('#0b1220')
+ expect(getComputedStyle(document.documentElement).getPropertyValue('--text').trim()).toBe('#e6eef8')
+ })
+})
+
+test('applies light CSS custom properties when theme is light', async () => {
+ ;(useTheme as jest.Mock).mockReturnValue({ resolvedTheme: 'light' })
+
+ render(
+
+ child
+ ,
+ )
+
+ await waitFor(() => {
+ expect(getComputedStyle(document.documentElement).getPropertyValue('--bg').trim()).toBe('#ffffff')
+ expect(getComputedStyle(document.documentElement).getPropertyValue('--text').trim()).toBe('#0b1220')
+ })
+})
diff --git a/components/theme-provider.tsx b/components/theme-provider.tsx
index bf85d22..b9a0d51 100644
--- a/components/theme-provider.tsx
+++ b/components/theme-provider.tsx
@@ -1,8 +1,48 @@
'use client'
import * as React from 'react'
-import { ThemeProvider as NextThemesProvider, type ThemeProviderProps } from 'next-themes'
+import {
+ ThemeProvider as NextThemesProvider,
+ useTheme,
+ type ThemeProviderProps,
+} from 'next-themes'
+
+const ROOT_CSS_VARS: Record = {
+ 'bg': { light: '#ffffff', dark: '#0b1220' },
+ 'text': { light: '#0b1220', dark: '#e6eef8' },
+ 'muted': { light: '#6b7280', dark: '#9aa4b2' },
+ 'accent': { light: '#0ea5e9', dark: '#38bdf8' },
+}
+
+function ThemeCustomProps() {
+ const { resolvedTheme } = useTheme() as { resolvedTheme?: string }
+
+ React.useEffect(() => {
+ const theme = resolvedTheme ?? 'light'
+ Object.entries(ROOT_CSS_VARS).forEach(([name, val]) => {
+ const value = theme === 'dark' ? val.dark : val.light
+ try {
+ document.documentElement.style.setProperty(`--${name}`, value)
+ } catch (e) {
+ // ignore in non-DOM environments
+ }
+ })
+ }, [resolvedTheme])
+
+ return null
+}
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
- return {children}
+ return (
+
+
+ {children}
+
+ )
}