Skip to content

feat(palette): adopt imprint — new categorical palette + named API + frontend rebuild#7692

Merged
MarkusNeusinger merged 24 commits into
mainfrom
feat/palette-variants-v1
May 26, 2026
Merged

feat(palette): adopt imprint — new categorical palette + named API + frontend rebuild#7692
MarkusNeusinger merged 24 commits into
mainfrom
feat/palette-variants-v1

Conversation

@MarkusNeusinger
Copy link
Copy Markdown
Owner

@MarkusNeusinger MarkusNeusinger commented May 23, 2026

Summary

Replaces the previous variant D palette (PR #7617) with imprint — anyplot's new 8-hue colourblind-safe categorical palette + 3 semantic anchors (amber for warning, theme-adaptive neutral and muted). Tuned for warm-paper rendering, validated against deuteranopia / protanopia / tritanopia, sits in the academic-publishing family next to Okabe-Ito, Paul Tol "muted", and ColorBrewer Set2.

Full design rationale: docs/reference/palette-variants-v3/decision-rationale.md. Earlier variants (v1, v2, expert reviews) preserved under docs/reference/palette-variants-*/ for design archaeology.

What's in this PR

Phase 1 — Backend foundation (core/)

  • NEW core/palette.py — single source of truth: 8 categorical hexes in hybrid-v3 sort order, 3 semantic anchors, named API (palette.green, palette.semantic.bad, …), sequential cmap imprint_seq (green→blue) + theme-adaptive diverging cmap imprint_div_{light,dark} (red↔midpoint↔blue), matplotlib registration.
  • core/images.py refactored — drops old 7 ANYPLOT_* constants, re-imports from core/palette.py. LIBRARY_COLORS rebuilt with library-brand-match strategy.

Phase 2 — Prompt system (18 files)

  • prompts/default-style-guide.md — full Color Philosophy rewrite with 8-hex hybrid-v3 table, new Semantic anchors section, series-count guidance with concrete ΔE_CVD numbers, optional outline pattern.
  • 11 library prompts (matplotlib / seaborn / plotly / bokeh / altair / plotnine / pygal / highcharts / ggplot2 / letsplot / makie) — ANYPLOT_PALETTE lists updated to 8 hexes + ANYPLOT_AMBER, cmaps renamed with new endpoints.
  • Quality + workflow prompts — VQ-07 scoring extended to positions 1-8 + 3 anchors, legacy variant-D hexes listed as auto-reject signals.

Phase 3 — Style guide doc

  • docs/reference/style-guide.md Section 4.1 rewritten as "The imprint Palette" with hue table, semantic-anchors table, hybrid-v3 sort rationale. Status colours (§4.5) and plot-only colours (§4.6) remapped onto imprint. CSS variables + Python implementation reference updated.

Phase 5a — Frontend palette page (/palette)

  • app/src/pages/PalettePage.tsx completely rebuilt across 5 iterations: real chroma wheel (CSS conic-gradient OKLCH + chroma fade) with hover tooltips, compare-with toggle (Okabe-Ito / Tol muted / ColorBrewer Set2 / anyplot previous), compact 4×2 slot grid with click-to-copy hex, sort toggle (imprint default ↔ CVD-optimal max-min) with inline trade-off info, semantic anchors cards, continuous cmaps gradient strips, copy snippets in 4 languages (Python / R / Julia / JS) with OKLCH toggle, collapsible WCAG audit + palette history.
  • theme/index.tscolors.okabecolors.imprint, semantic colours remapped.
  • styles/tokens.css--ok-*--imprint-*, code-syntax theme rebuilt for both light and dark.
  • components/PaletteStrip.tsx — 8-hex imprint set, optional hexes prop.

Phase 5b — Frontend consumers

  • LandingPage.tsxCLUSTER_PALETTE + 7-Okabe swatch row swapped (now click-to-copy), palette_okabe_ito analytics event gone.
  • MapPage.tsxCLUSTER_COLORS rebuilt with 8 imprint hexes.
  • AboutPage.tsx, ScienceNote.tsx — palette prose reframed around imprint.
  • CodeShowcase.tsx, CodeHighlighter.tsx — syntax hexes updated, okabeItoThemeimprintTheme.
  • LandingPage.test.tsx — drops the gone Okabe-Ito tracking-event test.

Final audit sweep

  • docs/reference/plausible.md (gone event row), .serena/memories/style_guide.md (Color section), scripts/style-variants.yaml (palette_tableau map), scripts/palette-analysis.py + docs/reference/anyplot-landing-mockup.html (HISTORICAL markers). Historical / comparison references (Okabe-Ito as family-neighbour, variant-D hexes as auto-reject signals in VQ-07, palette-variants exploration scripts) preserved intact.

Intentionally NOT in this PR (Phase 4)

7 plot implementations under plots/**/implementations/python/*.py still hardcode the old variant-D palette inline. Per the design discussion these stay untouched and will pick up imprint via the next /regen cycle, when the new prompts kick in.

Validation

  • yarn tsc --noEmit — clean
  • yarn lint — 0 errors (2 pre-existing warnings, neither palette-related)
  • yarn test --run507 / 507 passing
  • Backend smoke-test confirms named-API + cmap registration
  • Visual smoke tests via chrome-devtools on /, /palette, /map, /about

Test plan

  • Verify /palette page renders the chroma wheel, palette grid, semantic anchors, cmap previews, collapsibles
  • Try the compare-with toggle (Okabe-Ito / Tol muted / Set2 / anyplot previous) — overlay rings appear on the wheel
  • Try the sort toggle (imprint default ↔ CVD-optimal) — grid + strip + copy snippet all reorder
  • Click a swatch in the grid — copies hex to clipboard, swatch flips to "copied ✓"
  • Switch OKLCH toggle in the copy section — all 4 language snippets switch notation
  • Expand the WCAG audit and palette history collapsibles
  • Verify LandingPage palette section + map cluster preview render with imprint colours
  • Sanity-check dark mode on / and /palette
  • Watch Cloud Build: OG image regeneration should pick up the new LIBRARY_COLORS

🤖 Generated with Claude Code

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants