Implement M1.5 visual design foundation: tokens, IBM Plex, theme toggle, chart themes

This commit is contained in:
2026-06-05 01:29:10 +03:00
parent 547edb85e4
commit 22f0556ef8
31 changed files with 713 additions and 136 deletions
@@ -139,7 +139,7 @@ export const lightChartConfig: Config = {
view: { stroke: 'transparent' },
};
export const experimentalChartConfig: Config = {
export const darkChartConfig: Config = {
background: 'transparent',
font: '"Inter", sans-serif',
title: { fontSize: 15, fontWeight: 600, color: '#f4f4f5' },
@@ -167,7 +167,7 @@ import type { UiTheme } from './theme'; // core-local — never import from src/
const CHART_CONFIG: Record<UiTheme, Config> = {
light: lightChartConfig,
experimental: experimentalChartConfig,
dark: darkChartConfig,
};
export function chartConfigFor(theme: UiTheme): Config {
@@ -190,6 +190,26 @@ re-rendering picks up the new config and the chart restyles automatically.
- **Don't** let the user's stored spec carry a `config`; the theme config is
applied at embed time via the embed options, leaving the spec theme-agnostic.
### Theme flow (end to end)
Theme spans several layers; the path is:
`AppStore.uiTheme` (+ `toggleTheme`) → `orchestration/theme.ts` mirrors it onto
`<html data-theme>` and writes through to `infrastructure/settings-store.ts`
(localStorage `ui.theme`). On load, `initTheme()` — called from `main.tsx`
**before** `createRoot().render` — hydrates the saved theme. Chart and editor
follow by subscribing to `uiTheme`: `LivePreview` re-embeds with
`chartConfigFor(theme)`, `SpecEditor` sets the Monaco theme. UI chrome repaints
purely from the `[data-theme]` token swap in `styles/tokens.css`. The header
`ThemeToggle` is the user control.
- **Do** hydrate the theme **synchronously before first paint** — an async
hydrate (e.g. inside `initApp`) flashes the default theme on load.
- **Do** keep the store browser-free: the `data-theme` write and the localStorage
write-through live in `orchestration/theme.ts`, never in the store or a component.
- The control currently lives in the header; spec §07 houses it in the Settings
modal (M5), which will share the same `ui.theme` key.
---
## 4. Field-Name Escaping