feat(ui,sdk): Data colours scheme control — Pastel/Vivid/Muted (OB-379)#109
Merged
Conversation
…B-379)
Add a global "Data colours" appearance control that switches the data-colour
scheme (pastel default / vivid / muted) live across every data surface, and
persist it via the same appearance path as the other knobs.
- themes: `AppearanceOptions.dataColors` (default 'pastel'); `normalizeAppearance`
fills missing → pastel and drops invalid (mirrors the sidebar knob).
- control: Segmented "Data colours" in AppearanceSettings + en.ts strings
(appearance.dataColors{,Hint,Pastel,Vivid,Muted}); no brand names.
- reactivity: ThemeProvider calls `applyDataColors(scheme)` (CSS-var surfaces:
chips/dots/status recolour live) and wraps a `DataSchemeProvider`. Concrete-hex
surfaces can't read var() so they thread the active scheme: db charts
(`chartColor(…, scheme)`), kit charts (`paletteFor(scheme)`), map pins
(`swatchHex(…, scheme)`) via `useDataScheme()`; `swatchHex`/`seriesHex` gain a
scheme param.
- export: toHtml/toSlideDeck/toHtmlSite thread `scheme` through RenderCtx so
chips, status-light CSS, drawn kit charts and the live runtime inline the
active scheme (self-contained). The viewer bundle is told the scheme via
`window.__OB_DATA_SCHEME` (ViewerApp `DataSchemeProvider` + applyDataColors).
- tests: normalizeAppearance default/keep/drop; control switch persists +
recolours vars; export bakes the chosen scheme.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X78XTAemKrFw1uJpDpCEaG
… review nits) - muted status lamps: raise the LIGHT fill of green/yellow/red +12% saturation (hue kept) so they read as a clear red/yellow/green traffic light while staying in the muted family (still well below vivid). The dark fill keeps the desaturated wash (mode-variant for these three), and chips/series-of-other-hues are untouched. New light fills: green #70b88b, yellow #bfa969, red #bc6c6c. The dataColors drift guard's audit derivation is updated to match (Guard A green). - export: clamp `scheme` to DATA_COLOR_SCHEMES at the entry (safeScheme) before it reaches `window.__OB_DATA_SCHEME`/palette lookups — JSON.stringify doesn't escape </script>, so this keeps the injection safe for any future unnormalized caller. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X78XTAemKrFw1uJpDpCEaG
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
OB-378 unified data colours to one soft-pastel default, but there was no way to change the scheme. Goal (OB-374) called for configurable colour schemes in Appearance. Board: OB-379.
Solution
A "Data colours" Segmented control in Appearance switches the scheme: Pastel (default) / Vivid / Muted. Switching re-colours tag chips, status lights, kit + db charts, and map pins live. CSS-var surfaces recolour for free; concrete-hex surfaces (SVG fills, Leaflet pins, kit charts) thread the active scheme via a
DataSchemeProvider/useDataScheme()context. Exports inline the active scheme (self-contained; thewindow.__OB_DATA_SCHEMEhandoff is a validated enum end-to-end + clamped). New deps: none.Reviews — Devon (design) + Quinn (code), both CLEAR-WITH-NITS, all nits applied: the Muted status trio was punched up ~12% for a clearer traffic-light; the export scheme was clamped for defense-in-depth.
Before / After
Light + dark, all three schemes (chips, status lights, bar chart, donut):


Test procedure
pnpm verifygreen: sdk 171 · ui 937 · server 586 · e2e 251+40. Palette guard re-derives every value (incl. the punched muted status); export tests assert per-scheme hexes.Operational notes
chore/artifacts.Footer: verify green (sdk 171 · ui 937 · server 586 · mcp 40); design (Devon) + code (Quinn) gates cleared; three-scheme render owner-approved.
🤖 Generated with Claude Code
https://claude.ai/code/session_01X78XTAemKrFw1uJpDpCEaG