Problem
The site uses a fixed warm off-white canvas (#fbfaf7) with no prefers-color-scheme: dark handling. Students reading late at night or in dark environments get no accommodation. Dark mode is increasingly expected and easy to miss in initial builds.
Suggested approach
All design tokens live in understanding-ai/src/design.js as a single c object. The cleanest implementation:
- Add a
darkMode object to design.js with overridden token values:
export const darkTokens = {
canvas: '#18181b',
canvasSoft: '#1f1f23',
ink: '#f0efe8',
inkSec: '#b4b0a8',
inkMute: '#6b6760',
hairline: '#2e2d2a',
primary: '#7b6cfd', // slightly lighter for contrast on dark bg
primaryBg: '#1e1b3a',
primaryDeep: '#a09cfd',
primaryPress: '#6b5ef0',
};
-
In App.jsx, detect window.matchMedia('(prefers-color-scheme: dark)') and pass the appropriate token set down via context.
-
Components consume c from the context rather than importing directly — or a simpler approach: use CSS custom properties (--c-canvas, --c-ink, etc.) set at :root and override with @media (prefers-color-scheme: dark).
CSS custom properties is the simpler path since it doesn't require changing how components import c.
Considerations
- The
design.js inline-style approach makes CSS custom properties require a small refactor (replace c.canvas with var(--c-canvas) everywhere)
- Alternatively, a React context +
useTheme() hook keeps the inline style approach but adds a context layer
- A manual toggle (in addition to OS preference) is a nice-to-have, not a requirement
Acceptance criteria
- Site respects
prefers-color-scheme: dark with a dark palette
- Text contrast meets WCAG AA on both light and dark backgrounds
- Transition between modes is smooth (no flash of wrong theme on load)
Problem
The site uses a fixed warm off-white canvas (
#fbfaf7) with noprefers-color-scheme: darkhandling. Students reading late at night or in dark environments get no accommodation. Dark mode is increasingly expected and easy to miss in initial builds.Suggested approach
All design tokens live in
understanding-ai/src/design.jsas a singlecobject. The cleanest implementation:darkModeobject todesign.jswith overridden token values:In
App.jsx, detectwindow.matchMedia('(prefers-color-scheme: dark)')and pass the appropriate token set down via context.Components consume
cfrom the context rather than importing directly — or a simpler approach: use CSS custom properties (--c-canvas,--c-ink, etc.) set at:rootand override with@media (prefers-color-scheme: dark).CSS custom properties is the simpler path since it doesn't require changing how components import
c.Considerations
design.jsinline-style approach makes CSS custom properties require a small refactor (replacec.canvaswithvar(--c-canvas)everywhere)useTheme()hook keeps the inline style approach but adds a context layerAcceptance criteria
prefers-color-scheme: darkwith a dark palette