From 71fb144fa0a54488724565a62c5c53558acc014a Mon Sep 17 00:00:00 2001 From: Harbduls Date: Mon, 1 Jun 2026 15:32:44 +0100 Subject: [PATCH] Added theme consistency --- components/__tests__/theme-provider.test.tsx | 51 ++++++++++++++++++++ components/theme-provider.tsx | 44 ++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 components/__tests__/theme-provider.test.tsx 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} + + ) }