Chart Color System

io.github.socraticstatic由 GitHub 账号 socraticstatic 发布v0.1.2更新于 Oct 24, 2026

Solve, audit and simulate colorblind-safe chart palettes. WCAG contrast, OKLab ΔE. Read-only.

已验证Streamable HTTP可网页运行数据与分析媒体与设计

概览

AI 生成的概览

一个远程 MCP 服务器,用 OKLab 色差与 WCAG 对比度计算来求解、审计并模拟色盲友好的图表配色。

可以做什么
生成 1 至 12 色的分类图表配色,可将品牌色按槽位锁定为锚点,并返回最差配对距离与完整无障碍审计。审计现有图表颜色:在正常视觉及四种色觉缺陷下的两两 OKLab 色差,以及每种颜色相对图表背景的 WCAG 2.2 非文本对比度,给出通过/警告/失败结论。模拟每种颜色在绿色盲、红色盲、蓝色盲及全色盲读者眼中的样子。构建均匀间隔的 OKLab 顺序或发散色阶,并附带背景对比度审计。
适用场景
适合在为图表和仪表盘挑选或复核配色时使用,希望得到可辩护的无障碍数据而非凭感觉判断;也适合需要说明配色在色盲读者眼中效果时使用。
运行要求
远程 streamable HTTP 端点;未声明任何软件包、账户、API 密钥或环境变量。助手需要能访问该托管端点的网络。
安装前请注意
该服务器被描述为只读,仅计算颜色值,不会修改图表或数据。其结论仅供参考:README 指出所配置的色差阈值是刻意设定的低门槛而非感知保证,尤其在超过约六种色相时。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Chart Color System,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

交给智能体安装

把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。

阅读 https://sourceweft.com/mcp/io.github.socraticstatic%2Fchart-color-system/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。

查看智能体所依据的安装指南

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "chart-color-system": {
      "type": "http",
      "url": "https://chart-color-mcp.vercel.app/mcp"
    }
  }
}

README

Chart Color & Encoding System

By Micah Boswell (socraticstatic). Copyright © 2026 Micah Boswell. All rights reserved.

A token-driven, math-backed palette system for ECharts dashboards. Generates categorical, sequential, and diverging palettes, and pairs every color slot with a matching dash, decal, and marker shape so meaning survives even when color fails. Categorical palettes are audited pairwise against WCAG contrast, color-vision deficiency (CVD) simulation, and grayscale. Sequential and diverging ramps are audited for background contrast and built for monotonic OKLab lightness (their grayscale-survival property); pairwise ΔE separation is intentionally not applied to ramps, whose stops are designed to be perceptually adjacent. Honesty note: past ~6 hues, no palette keeps colors reliably distinct under dichromacy — the configured CVD/ΔE floors in constraints.ts are deliberately minimal at high N, and the redundant dash/decal/shape encodings are what carry series identity.

Current version: 0.7.0 (PALETTE_VERSION in src/charts/version.ts; history in CHANGELOG.md).


Jobs To Be Done

Primary

  • JTBD-1 — Pick a palette I can defend (contrast + CVD + grayscale audited).
  • JTBD-2 — Charts stay readable for colorblind users (color + dash + decal + shape).
  • JTBD-3 — Same entity stays the same color everywhere.
  • JTBD-4 — Doesn't break when series count changes (graceful Top-N + Other).
  • JTBD-5 — Light and dark mode equally good.
  • JTBD-6 — Right chart-type encoding chosen automatically.
  • JTBD-7 — Prove it works before shipping (live QA harness).

Secondary

  • JTBD-8 — Per-user color pin (localStorage, scoped by entity ID).
  • JTBD-9 — Brand-locked anchor slots seed the optimizer.
  • JTBD-10 — Surface infeasibility with documented relaxation order.
  • JTBD-11 — Instant theme switch (precomputed cache).
  • JTBD-12 — Stay maintainable (no raw color literals; versioned palette; docs always current).

Out of scope (named, not built): multi-tenant solving, SSR/PDF export, telemetry, task-based usability study.


Architecture

text
  index.css tokens (HSL)         │         ▼  constraints.ts  ──────┐  brand/semantic locks ─┤  background + chrome  ─┼──►  optimizer (OKLab + CVD + gamut)  N + posture          ─┤              │  reserved slots       ─┘              ▼                                ordered slot list                                (color, dash, decal, shape)                                       │                                       ▼                          echartsTheme.ts adapter                                       │                                       ▼                          ECharts components (demo)                                       │                                       ▼                          QA harness (CVD / grayscale / contrast)

Deliverables

#DeliverableServes JTBD
1Token contract (src/index.css + tailwind.config.ts)1, 5, 9, 12
2Constraint config (src/charts/constraints.ts)1, 9, 10
3Palette optimizer (src/charts/palette/)1, 2, 4, 10
4Aligned encoding scales (src/charts/encoding.ts)2, 3, 6
5ECharts theme adapter (src/charts/echartsTheme.ts)5, 6, 11
6Demo route /charts7
7QA harness (CVD / grayscale / contrast / posture / N)2, 7, 10
8Test suite1, 2, 4, 12
9Override + versioning scaffolding8, 12
10This README.md12
11CHANGELOG.md12

Tiers

Tier 1 — Tokens & constraints

Semantic chart tokens in index.css (HSL, light + dark): surfaces, neutrals, status, anchors, states. Tailwind chart color group exposes them. constraints.ts defines ΔE thresholds, posture presets (kpi, comparative, exploratory), Top-N + Other overflow, and constraint-relaxation priority.

Tier 2 — Optimizer & encoding scales

  • palette/cvd.ts — Machado 2009 deutan/protan/tritan matrices.
  • palette/distance.ts — OKLab ΔE + worst-of-three CVD ΔE.
  • palette/gamut.ts — chroma-reduction gamut mapping into sRGB.
  • palette/categorical.ts — seeded farthest-point + simulated-annealing maximin solver.
  • palette/ramps.ts — monotonic-L OKLCH sequential and diverging ramps.
  • palette/assignment.ts — bipartite stable assignment when N changes.
  • encoding.ts — dashScale, decalScale, shapeScale indexed 1:1 with color.

Tier 3 — Adapter, demo, lifecycle

  • echartsTheme.ts reads CSS vars at runtime and emits an ECharts theme + helpers (buildLineSeries, buildBarSeries, buildVisualMap).
  • components/charts/EChart.tsx wraps echarts-for-react with atomic theme swap.
  • /charts is a constrained palette builder beside the chart preview: chart type, N, theme, vision preview, and fixtures are controlled from one place. Posture, palette family, and ramp shape are derived. The default N snap is capped to the runtime-probed safe max so out-of-the-box palettes clear every configured ΔE / CVD floor and WCAG 3:1 contrast with zero solver relaxations; the slider can be dragged past the safe cap into an educational range where the audit panel shows exactly which floors break.
  • Every render runs the accessibility audit (audit.ts): per-vision OKLab ΔE (normal + deutan + protan + tritan + achromatopsia) against per-mode thresholds, plus WCAG 2.2 SC 1.4.11 (≥ 3:1) contrast vs. background. Result is shown as a pass / warn / fail badge with per-vision detail.
  • setEntityColor(entityId, slotIndex) persists per-user pins in localStorage.
  • PALETTE_VERSION aligns with CHANGELOG.md.

Run

bash
npm installnpm run dev

Then open the preview and navigate to /charts.

Tests

bash
npx vitest run

Covers the palette primitives (stableAssign, sequentialRamp L-monotonicity, divergingRamp length, aligned encoding scales), solveCategorical property tests across N=2..8 (determinism, in-gamut sRGB, threshold-or-relaxation contract, lock-honoring), entity pins (permutation safety, collision bumping, paired remap of color/dash/decal/shape), URL state round-trips, and fixture determinism + messy-mode characteristics (nulls on lines, missing heatmap cells, diverging outliers).

Reading the accessibility harness

  • Overall verdict: pass (all modes pass + WCAG ≥ 3:1), warn (≤ 1 vision mode fails, contrast still passes), or fail.
  • Per-vision tiles: minimum pairwise ΔE under each simulation, vs. the configured threshold. Note the CVD and normal-vision thresholds (constraints.ts) are deliberately low floors, not perceptual guarantees — they exist to catch outright collisions while the dash/decal/shape scales carry identity at high N.
  • Worst contrast vs. background: WCAG 2.2 SC 1.4.11 ratio for non-text marks; threshold ≥ 3:1.
  • Best-practice rationale: one-line explanation of why this chart type has its specific limits, plus per-N warnings (e.g. "Pie charts above 5 slices misrepresent magnitudes").

Exporting a palette

The green Export palette button on /charts opens a tabbed dialog with five emitters from src/charts/paletteExport.ts:

  • CSS variables — :root (or .dark) block with --chart-bg, --chart-cat-N, --chart-seq-N, --chart-div-N, plus semantic positive/negative. When Compare is on with normal vision, Variant B is emitted under [data-chart-variant="b"].
  • Tailwind config — chart.cat/seq/div map that references the CSS vars above, paste-ready under theme.extend.colors.
  • ECharts theme — full registerTheme payload (color, backgroundColor, axis/legend/tooltip, sequential + diverging visualMap ramps).
  • Figma Tokens — Tokens Studio / W3C-style JSON with chart.{surface,semantic,categorical,sequential,diverging} and $metadata.generator.
  • SVG swatches — single-page printable sheet labeled with hex + slot index.

The Export audit report button (next to it) still produces the standalone HTML audit (charts + warnings + accessibility metrics, single-variant or A vs. B).

Palette builder

The only active builder controls live beside the chart preview. They update the rendered chart immediately, clamp N to the safe built-in range for the selected kind/theme, and clear any stale inline token overrides on load so built-in palettes remain compliant.

Coach tour

A coach tour auto-opens on first visit (localStorage["chart-tour-seen-v1"]) and walks through the chart-side builder controls and export flow. Replay it anytime via Take the tour in the page header.

Presets

The Presets panel ships 6 curated starters ("Finance KPI", "Analytics exploratory", "Board / comparative", "Marketing share", "Ops heatmap", "Variance / diverging") and lets you save your own named (kind, n, theme) configurations under localStorage["chart-palette-presets-v1"]. Color overrides are stored separately so presets stay solver-stable across palette updates. The Compare presets sub-panel lets you pick any two (curated, user, or the live builder state) and shows a side-by-side diff of chart kind, family, posture, N, recommended N, max N, and theme — differing rows highlighted in warning tint, ⚠ flags N above the kind's recommended ceiling.

Entity pins

The Entity pins panel (categorical charts) lets you lock a series to a specific slot — color, dash, decal, and shape together — so the same entity keeps the same identity across filters, reloads, and dashboards. "Auto" means "let the solver assign the next free slot in order"; picking Slot k writes the pin to localStorage["chart-entity-color-pins-v1"] via setEntityColor. Collisions (two entities pinning the same slot) are auto-resolved — the later entity is bumped to the next free slot and listed under "Collisions". Implements JTBD-3 ("keep the same entity the same color everywhere").

Benchmark vs. published systems

For categorical charts, a Benchmark vs. published systems table scores the current solver palette next to Tableau 10, IBM Carbon Categorical, ColorBrewer Set2, Observable 10, and Material 700 — using identical math (min pairwise ΔE in OKLab, worst-of-three CVD ΔE, worst contrast vs. your current background). ★ marks the winner per column.

Density preview

For categorical charts, the Density preview renders every slot at realistic chart-element sizes (11px legend swatch, 2px line stroke, 4px bar, 8px scatter dot, deterministic sparkline) against the active background — so you catch slots that vanish at small sizes before shipping.

Copy decision rationale

The Copy rationale button inside the Explain panel copies a paragraph-formatted decision summary (inputs · family · posture · N · solver/ramp note · relaxations · accessibility verdict) to the clipboard, ready to paste into a PR, ticket, or design spec.

Shareable deep links

The Copy share link button (next to Export) writes the current builder configuration — chart kind, N, theme, vision, compare flag, and Variant B — into the URL hash and copies a permalink to your clipboard. Anyone who opens the link lands on the exact same configuration. Brand-anchor color overrides stay per-user in localStorage and are intentionally excluded from the link.

Ready-to-paste code snippet

For categorical charts, the Ready-to-paste React + ECharts snippet panel emits a self-contained <KindChart>.tsx component with the audited palette, dashes, decals, shapes, and chrome tokens baked in. It depends only on echarts + echarts-for-react — no design-tool runtime — so engineers can ship the chart without adopting the whole token system. Show/hide, copy, or download as .tsx.

Semantic role audit

For categorical charts, the Semantic role audit scores each semantic token (positive, negative, target, forecast, muted, other) for WCAG ≥ 3:1 contrast vs. the chart background and for collisions with the current categorical palette under both normal and CVD vision. Surfaces the silent failure where a "positive" green KPI bar blends into a categorical series for deutan/protan viewers.

Vision matrix

The Vision matrix renders the current chart five times side-by-side — normal, deuteranopia, protanopia, tritanopia, and grayscale — using the same SVG color-matrix filters that back the single-mode preview. Scan all five at once instead of toggling, and you'll see immediately which series collapse for any audience.

Glossary

The collapsible Glossary panel at the bottom of /charts defines every term the tool surfaces (ΔE, OKLab, CVD, WCAG 2.2 SC 1.4.11, posture, anchor, decal, dash, shape, relaxation, Top-N + Other, stable assignment), each with a plain-language summary, a longer explanation, and a pointer to the source file that implements it.

Emphasis preview

For line, step-line, area, stacked-area, bar, stacked-bar, grouped-bar, and horizontal-bar kinds, the Emphasis preview lets you pick a hero series and renders the chart with that slot at full chroma while every other series collapses to --chart-muted. Use to verify the storytelling pattern (one entity in focus, the rest as context) holds up under the audited palette before handing the chart to engineering.

Insight callouts

For categorical charts, Insight callouts auto-generates plain-English observations about the palette's shape: most and least saturated slots (with multiplier vs. the average), hue families covered, tightest CVD pair, tightest normal-vision pair, tightest contrast-vs-background slot, and OKLab lightness spread (grayscale-survival proxy). Descriptive, not prescriptive.

Messy / realistic fixtures

The Fixtures toggle in the palette builder (synthetic / messy) swaps the underlying data behind line / step-line / area / stacked-area / bar / stacked-bar / grouped-bar / horizontal-bar / heatmap / diverging-bar / diverging-heatmap. Synthetic is smooth sine/cosine data with no missing values, ties, or outliers — pretty, and hides palette weaknesses. Messy mirrors real dashboards: long-tail magnitudes (first series dominates), one near-zero "dead" series, one spiky outlier series, ~6 % missing values, heavy hot spots + missing cells in heatmaps, and extreme outliers + near-midpoint ties in diverging. Both modes are deterministic via a seeded PRNG, so the same configuration always renders the same fixture. Use it to test palettes against the patterns that actually break them (near-zero stacks vanishing, tied middle series becoming indistinguishable, near-midpoint diverging cells merging into the ramp midpoint).


Documentation maintenance contract

Every change in this project must, in the same change:

  1. Update README.md if scope, architecture, deliverables, JTBD, dependencies, or run/usage changes.
  2. Add an entry under ## [Unreleased] in CHANGELOG.md (Added / Changed / Fixed / Removed / Security).
  3. Bump PALETTE_VERSION if constraints, anchors, or optimizer behavior change in a user-visible way.

This rule is persisted to project memory (mem://index.md).


Tech notes

  • Dependencies: culori, echarts, echarts-for-react.
  • Client-side only.
  • OKLab for math, HSL for CSS, hex/rgba into ECharts via the adapter.
  • Seeded PRNG → reproducible palettes.
  • Solver runs once per (theme, posture, N) at module init; cached.

Sponsor

If this system saves you a week of arguing about chart colors, you can support the work here: github.com/sponsors/socraticstatic


License

Copyright © 2026 Micah Boswell. Dual-licensed — see LICENSE.

The palette engine is MIT (LICENSE-MIT): src/charts/index.ts, src/charts/palette/**, constraints.ts, encoding.ts, audit.ts, version.ts. It ships to npm as chart-color-system. Palettes and tokens you generate with it — including anything from Export or Copy-snippet — are yours, no attribution required.

Everything else is proprietary (LICENSE-PROPRIETARY): the React application, its UI components, the demo harness, and the written content. No part may be copied, modified, or distributed without express written permission.

Building the package

bash
npm run build:lib     # → dist-lib/, an MIT-licensed, publishable package

The published version tracks PALETTE_VERSION, not the app version: a version bump means the colors may have moved.

Publishing with 2FA on

npm 11 defaults to auth-type=web, which bounces through a browser and fails on accounts using a passkey or an unavailable second factor. Use the terminal flow instead, which asks for username, password, and OTP directly:

bash
npm run login:npm     # npm login --auth-type=legacy

Then publish, passing the current OTP through to npm publish:

bash
npm run publish:lib -- --otp=123456

License & attribution

Dual-licensed: the palette engine is MIT; the application is proprietary, source-available (see LICENSE). If this ends up inside a commercial or enterprise product, credit Micah Boswell — Chart Color System (https://socraticstatic.github.io/Visualizations/) in your docs, about screen, or credits. For the engine that's the ask on top of MIT's required license preservation; for the application code it's a condition of any permitted commercial use.

来源:README.md,提交 6095ece

工具

4

solve_palette

Solve a chart palette

Generate a categorical chart palette of n colors (1-12) that maximizes perceptual separation under normal vision and colorblindness, with the given brand colors locked as anchors in slot order. Returns the palette, the worst pair distances, the engine's relaxation notes, a full accessibility audit against the background, and a link to open it in the app. Honest cap is 6 slots; above that the result says so.

输入参数ngridanchorsposturebackground

audit_palette

Audit a chart palette

Audit existing chart colors for accessibility: pairwise OKLab separation under normal vision, deuteranopia, protanopia, tritanopia and achromatopsia, plus WCAG 2.2 non-text contrast (3:1) of every color against the chart background. Returns a pass / warn / fail verdict with the numbers behind it. Set ramp=true for sequential or diverging scales, whose steps are meant to be close.

输入参数rampcolors必填background

simulate_palette

Simulate colorblind vision

Show what each color looks like to readers with deuteranopia, protanopia, tritanopia or achromatopsia (published Machado 2009 matrices), so an assistant can describe or render the palette as a colorblind reader sees it.

输入参数modescolors必填

build_ramp

Build a sequential or diverging ramp

Build an evenly spaced perceptual (OKLab) color scale: sequential from start to end, or diverging from start through mid to end. Returns the steps and a background-contrast audit (pairwise separation is not judged for ramps).

输入参数end必填midkind必填start必填stepsbackground

版本历史

2
  1. v0.1.2最新Oct 4, 2026
  2. v0.1.1Sep 16, 2026

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通必需25 分
  • 已声明认证方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分

    请在仓库或注册中心条目中声明许可证。