diff --git a/src/App.tsx b/src/App.tsx index 969d435..6c1d22a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,5 @@ import { BrowserRouter } from 'react-router-dom'; -import { useMemo } from 'react'; +import { useMemo, useEffect } from 'react'; import { ThemeProvider, createTheme } from '@mui/material/styles'; import { useTLDraw } from './contexts/TLDrawContext'; import { theme } from './services/themeService'; @@ -10,26 +10,40 @@ import AppRoutes from './AppRoutes'; import { ErrorBoundary } from './components/ErrorBoundary'; import React from 'react'; -const App = React.memo(() => { +/** + * Syncs tldraw's color scheme to data-color-mode on . + * Must live inside TLDrawProvider so useTLDraw() reads live preferences. + * This activates the [data-color-mode="dark"] overrides in cc-design-system.css. + * tldraw itself uses tl-theme__dark class on .tl-container — we mirror that + * to the document root so --cc-* token overrides apply globally. + */ +const DarkModeSync: React.FC = () => { const { tldrawPreferences } = useTLDraw(); + const prefersDarkMode = + typeof window !== 'undefined' && + window.matchMedia('(prefers-color-scheme: dark)').matches; + useEffect(() => { + const scheme = tldrawPreferences?.colorScheme ?? 'system'; + const isDark = scheme === 'dark' || (scheme === 'system' && prefersDarkMode); + document.documentElement.setAttribute('data-color-mode', isDark ? 'dark' : 'light'); + }, [tldrawPreferences?.colorScheme, prefersDarkMode]); + + return null; +}; + +const App = React.memo(() => { const prefersDarkMode = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches; const appTheme = useMemo(() => { - let mode: 'light' | 'dark'; - - if (tldrawPreferences?.colorScheme === 'system') { - mode = prefersDarkMode ? 'dark' : 'light'; - } else { - mode = tldrawPreferences?.colorScheme === 'dark' ? 'dark' : 'light'; - } - - return createTheme({ - palette: { mode }, - }); - }, [tldrawPreferences?.colorScheme, prefersDarkMode]); + // App is outside TLDrawProvider so tldrawPreferences is always null here. + // Theme defaults to OS preference; DarkModeSync (inside TLDrawProvider) handles + // updating data-color-mode once tldraw preferences are loaded. + const mode = prefersDarkMode ? 'dark' : 'light'; + return createTheme({ palette: { mode } }); + }, [prefersDarkMode]); return ( @@ -37,6 +51,7 @@ const App = React.memo(() => { + diff --git a/src/utils/tldraw/tldraw.css b/src/utils/tldraw/tldraw.css index c32e4b4..f69ea8f 100644 --- a/src/utils/tldraw/tldraw.css +++ b/src/utils/tldraw/tldraw.css @@ -1,2 +1,12 @@ @import url("@tldraw/tldraw/tldraw.css"); @import url('./cc-design-system.css'); + +.tl-container { + --color-panel: var(--cc-bg-panel); + --color-text: var(--cc-text-primary); + --color-muted: var(--cc-border); + --color-muted-1: var(--cc-border-strong); + --color-background: var(--cc-bg-canvas); + --color-selected: var(--cc-selected); + --color-accent: var(--cc-action-primary); +}