From 6b80642e0c4515c7e620780c1f04669e535570cf Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Mon, 13 Jul 2026 09:53:38 -0500 Subject: [PATCH] Fix dark mode in the dev test server The dev harness did not fully honor dark mode: - dev/testActivity.json pinned DoenetML 0.7.4, so each embedded DoenetViewer loaded a @doenet/standalone bundle that predates dark mode. The iframe body was darkened but the document text stayed in light-mode colors (black-on-black). Bump to 0.7.20-dev.332, the latest dev build, which includes dark-mode support and matches the installed @doenet/doenetml-iframe. The stable 0.7.20 release predates the dark-mode work, so it is not sufficient. - dev/App.tsx: theme the harness chrome to follow the selected darkMode instead of being hardcoded light. Theme the header box and controls, sync the page backdrop to the viewer's --canvas color so the area around the activities matches, and pin the chrome buttons' colors to the selection (dev/index.css keys button backgrounds off the OS prefers-color-scheme, which drifted out of sync and produced white-on-white). Dev-only; no changes to shipped code under src/. Co-Authored-By: Claude Opus 4.8 (1M context) --- dev/App.tsx | 41 +++++++++++++++++++++++++++++++++++++---- dev/testActivity.json | 12 ++++++------ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/dev/App.tsx b/dev/App.tsx index 68f7340..dfd77d9 100644 --- a/dev/App.tsx +++ b/dev/App.tsx @@ -11,6 +11,7 @@ import { validateStateAndSource, } from "../src/Activity/activityState"; import { isReportScoreByItemMessage, isReportStateMessage } from "../src/types"; +import { useResolvedTheme } from "../src/utils/theme"; import type { ThemeSetting } from "../src/utils/theme"; function App() { @@ -55,6 +56,35 @@ function App() { darkMode, } = testSettings; + // Resolve the selected dark-mode setting so the dev-harness chrome (the + // gray header box and its controls) tracks the same theme as the viewer + // below it, rather than staying light. + const resolvedTheme = useResolvedTheme(darkMode); + + // Keep the whole dev page — the body backdrop and native form controls — + // in step with the selection, not just the OS preference that index.css + // keys off of. Match the backdrop to the viewer's `--canvas` color so the + // area below/around the activities doesn't read as a lighter black. + useEffect(() => { + const root = document.documentElement; + root.style.colorScheme = resolvedTheme; + root.style.backgroundColor = + resolvedTheme === "dark" ? "#121212" : "#ffffff"; + return () => { + root.style.colorScheme = ""; + root.style.backgroundColor = ""; + }; + }, [resolvedTheme]); + + // Native