# ztd charts > ztd charts (npm package ztd-charts) is a React 18+ chart library with 36 animated, interactive, accessible chart types drawn in pure SVG. It has zero runtime dependencies: react and react-dom are peer dependencies. Each chart can be written as a JSON spec { type, data, encoding, options, card } and rendered with , validated against a JSON Schema, drawn to PNG, SVG or HTML by the ztd-charts CLI, or picked and drawn by AI agents through a stdio MCP server. MIT license. Key facts: - Language: English by default. Locale "ko-KR" (a chart's locale prop, options.locale in a spec, or ) switches number formats (1.2만, 3.4억, ₩5,000) and the text charts write themselves (tooltips, screen reader sentences, badges) to Korean. - Theme: dark by default (ink cards, lime accent). theme="light" gives white cards with a sky-blue accent. Every color is a --ztd-* CSS variable. - Design: one highlighted item in the accent color, everything else neutral. adds a number, a bold title, a gray subtitle, a small square legend, a one-line takeaway and a level badge (Basic, Intermediate, Advanced; 기본, 중급, 심화 in Korean). - Accessibility: keyboard navigation (Tab, arrow keys, Enter), a screen reader description and a hidden data table on every chart, and the reduced motion setting. Install: - Library: `npm i ztd-charts` (React 18 or later) - CLI: `npx ztd-charts-cli `. Commands: list, info, schema, example, validate, render, init, suggest. Installed, the command is `ztd-charts`. Never run `npx ztd-charts`: that is the chart library, which has no command. Add `--locale ko` for Korean output. - MCP server in Claude Code: `claude mcp add ztd-charts -- npx -y ztd-charts-mcp` - MCP server in a JSON config (Claude Desktop, Cursor): `{ "mcpServers": { "ztd-charts": { "command": "npx", "args": ["-y", "ztd-charts-mcp"] } } }`. Tools: list_charts, get_chart_schema, validate_spec, render_chart, suggest_chart. - Agent skill: copy skills/ztd-charts/ from the repository to .claude/skills/ztd-charts/ (Claude Code) or .cursor/skills/ztd-charts/ (Cursor). Usage: ```tsx import { Chart, ChartCard, PieChart } from "ztd-charts"; const data = [{"device":"Mobile","sales":72},{"device":"Desktop","sales":23},{"device":"Tablet","sales":5}]; // A component. Encoding channels are props with the same name // The same chart from a JSON spec, card included ``` Channels whose prop name differs: gauge value -> valueKey, gauge target -> targetKey. Entry points: - `ztd-charts`: the 36 chart components (, and so on), , , , , , useChartData, number formatters - `ztd-charts/spec`: works without React. CHARTS (the registry), validateSpec, specSchema, schemaFor, suggestCharts, chartsIn, localizeDef, sample data - `ztd-charts/server`: renderSpecToSVG (a standalone SVG with the card frame), renderSpecToHTML, resolveSpecData - `ztd-charts/schema.json`: JSON Schema (draft 2020-12) for every spec. One chart: `ztd-charts/schema/charts/.schema.json` Spec: - type: one of the 36 types below. Aliases: doughnut -> donut, column -> bar, stackedBar -> bar, groupedBar -> bar, stacked -> area, streamgraph -> stream, radial -> radialBar, radialbar -> radialBar, progress -> gauge, progressRing -> gauge, kpi -> gauge, violin -> box, boxplot -> box, calendarHeatmap -> calendar, parallel-coordinates -> parallel, parallelCoordinates -> parallel, mekko -> marimekko, spider -> radar, ohlc -> candlestick, candle -> candlestick, stock -> candlestick, segment -> segmented, segmentedBar -> segmented, proportionBar -> segmented, stackedBar100 -> segmented, hist -> histogram - data: an array of row objects, { values }, { csv } or { url, format?, select? }. , the CLI and the MCP render_chart tool fetch the url. - encoding: channel -> field name. y can be an array of fields for wide tables. - options.highlight: Item to highlight. An index, a name, an array, or "max" | "min" | "first" | "last" | "none". Without it, each chart picks its own default (listed per chart in llms-full.txt). - options.format: Value format. "number" | "integer" | "percent" (values are already percents: 42 → "42%") | "ratio" (0.42 → "42%") | "compact" | "currency" (KRW for Korean locales, otherwise USD; for another currency pass Intl options with currency) | "decimal" or Intl.NumberFormat options. options.unit is text appended to each value. - Other common options: height, width, locale, animate, duration, easing (spring|easeOut|easeInOut|linear), stagger, reducedMotion, animateOnView, showLabels, tooltip, syncId, ariaLabel, description. Each chart adds its own options. - card: { number, title, subtitle, takeaway, level: "basic" | "intermediate" | "advanced" (Korean "기본" | "중급" | "심화" also accepted), legend: "auto" | "toggle" | [{ label, color }], sample, source, note, accent, download: true | ["csv", "svg", "png"] } - JSON Schema: https://unpkg.com/ztd-charts/schema/chart-spec.schema.json - Korean: from ztd-charts/spec, chartsIn("ko") and localizeDef(def, "ko") return Korean names, descriptions and example specs; specSchemaIn("ko") and schemaForIn(type, "ko") return the JSON Schema with Korean descriptions (specSchema() and schemaFor(type) are English); validateSpec(spec, { lang: "ko" }) and suggestCharts(rows, { lang: "ko" }) return Korean messages; GROUPS and LEVELS hold both labels Data helpers: - useChartData(url | async fn, { select, parse, refreshMs, init }) -> { data, loading, error, empty, reload } - parseCSV, fromRows (2D arrays, SQL rows + columns, Sheets values), fromObjects (key-value maps, column maps), melt, normalizeData - percentile(values, 95) and percentiles(rows, { by, value, p: [50, 95, 99] }) -> rows with p50, p95, p99 per group, for p95 latency charts. BoxPlot whiskers: [5, 95] sets whisker ends to percentiles. - Accessors accept a field name (dot paths ok) or a function (d, i) => value. Strings like "1,234", "12%", "₩5,000" are read as numbers. - shows matching states at chart height. Charts (type, component, English name, Korean name, level): - pie (, Pie chart, 파이 차트, basic): Each item's share of the whole. encoding: label, value. use: 2 to 4 items that add up to 100%. avoid: More than 4 items, or values close to each other (bars are more accurate). - donut (, Donut chart, 도넛 차트, basic): A share chart with the total in the center. encoding: label, value. use: The total matters as much as the shares. avoid: More than 6 items. - funnel (, Funnel chart, 퍼널 차트, basic): How much drops at each stage, with conversion rates. encoding: label, value. use: Ordered steps such as a sign-up or purchase flow. avoid: The steps have no order, or values grow from step to step. - waffle (, Waffle chart, 와플 차트, intermediate): Proportion on a 100-cell grid. encoding: label, value. use: A share reads better as a count, like '38 out of 100'. avoid: More than 4 items, or differences under 1% matter. - treemap (, Treemap, 트리맵, intermediate): Shares of a hierarchy shown as area. encoding: label, value, group?. use: Two levels of share at once, such as products within categories. avoid: Exact size comparison matters. - sunburst (, Sunburst, 선버스트, intermediate): A hierarchy drawn in rings. encoding: label, value, group?. use: A breakdown of 2 to 3 levels, such as channel > campaign. avoid: 4 or more levels, or more than 20 leaves. - waterfall (, Waterfall chart, 폭포 차트, intermediate): Breaks the change from a start value to an end value into its drivers. encoding: label, value, type?. use: Explaining why last month's revenue became this month's. avoid: More than 12 drivers. - pareto (, Pareto chart, 파레토 차트, intermediate): Bars sorted largest first with a cumulative share line. encoding: label, value. use: Seeing how few items make up 80% of the total. avoid: The item order means something (time order, for example). - marimekko (, Marimekko chart, 마리메코 차트, advanced): Two shares at once: width (column share) and height (share within the column). encoding: x, series, value. use: Revenue size by channel and device mix in one chart. avoid: More than 6 columns or more than 4 series. - heatmap (, Heatmap, 히트맵, intermediate): Values where two categories meet, shown as color depth. encoding: x, y, value. use: Finding patterns such as orders by weekday × hour. avoid: Exact value comparison matters. - radar (, Radar chart, 레이더 차트, intermediate): Compares several metrics at once. encoding: axis, value[], series?. use: Products or candidates scored on 5 to 8 metrics. avoid: More than 3 series (they overlap and get hard to read). - bubble (, Bubble chart, 버블 차트, intermediate): Three values at once: x, y and size. Without size it is a scatter plot. encoding: x, y, size?, label?. use: How three metrics relate, such as CPC, ROAS and spend by campaign. avoid: Dots overlap and sizes get hard to compare. - line (, Line chart, 라인 차트, basic): Change over time. encoding: x, y[], series?, lower?[], upper?[]. use: A metric over time, such as monthly users, alone or against other series. avoid: x is a category with no order. - area (, Area chart, 영역 차트, basic): Running totals and a changing mix (stacked, 100% stacked). encoding: x, y[], series?, lower?[], upper?[]. use: Seeing how each channel's traffic changes within the total. avoid: The exact value of each series matters. - stream (, Streamgraph, 스트림그래프, advanced): Many series as flowing bands that show size and change. encoding: x, y[], series?. use: 5 or more series where the rhythm of the flow matters, such as viewing by genre. avoid: You need to read exact values. - bar (, Bar chart, 막대 차트, basic): Grouped, stacked, 100% and horizontal bars, with optional lines on the same axis. encoding: x, y[], series?, line?[]. use: Comparing sizes across categories precisely. avoid: The flow over time is the point (a line works better). - radialBar (, Radial bar chart, 방사형 막대, intermediate): Ratios such as progress toward goals, drawn as rings. encoding: label, value. use: Showing progress on 3 to 6 goals in one view. avoid: Comparing values precisely (outer rings look longer). - gauge (, Gauge, 게이지, basic): One KPI's current value against its target. encoding: value, target?. use: Showing one value against its target, large. avoid: Comparing several values. - bullet (, Bullet chart, 불릿 차트, intermediate): Actual value against a target and bands (poor, fair, good). encoding: label, value, target?. use: Several KPIs with their targets in a small space. avoid: There is no target or band. - sparkline (, Sparkline, 스파크라인, basic): A small trend line next to a table cell or KPI. encoding: x?, y. use: The trend matters more than exact values. avoid: You need to read axis values. - slope (, Slope chart, 슬로프 차트, intermediate): Change in size and rank between two points in time. encoding: label, x?, value?. use: Comparing just two points in time, such as last year's and this year's share. avoid: 3 or more points in time (use a line or bump chart). - dumbbell (, Dumbbell chart, 덤벨 차트, intermediate): The gap between two values per item (before and after, target and actual). encoding: label, start, end. use: The gap is the story, such as before and after an improvement by region. avoid: There is only one value. - lollipop (, Lollipop chart, 롤리팝 차트, basic): A line and a dot instead of a bar. Stays light with many items. encoding: label, value. use: Rankings of 7 to 20 items, such as usage by feature. avoid: The differences between values are very small. - beeswarm (, Beeswarm, 비스웜, advanced): A distribution with every dot laid out without overlap. encoding: value, group?, label?. use: Seeing each user's value, group by group. avoid: Thousands of dots that overlap (use violin or ridgeline). - ridgeline (, Ridgeline, 릿지라인, advanced): Group distributions as overlapping, stacked curves. encoding: group, value. use: Comparing distributions across 5 to 12 groups, such as delivery time by region. avoid: 3 or fewer groups (a box plot is simpler). - sankey (, Sankey diagram, 생키 다이어그램, advanced): How much flows between stages. encoding: source, target, value. use: User flow from traffic source to purchase or drop-off. avoid: The flow loops back, or there are more than 30 nodes. - chord (, Chord diagram, 코드 다이어그램, advanced): How much groups send to and receive from each other. encoding: source, target, value. use: Two-way relationships, such as requests between teams. avoid: More than 10 groups. - calendar (, Calendar heatmap, 캘린더 히트맵, intermediate): Daily amounts on a weekly grid. encoding: date, value. use: The rhythm of daily activity, such as commits or orders. avoid: The period is shorter than a month. - bump (, Bump chart, 범프 차트, intermediate): Rank changes over time. encoding: x, series, rank?, value?. use: What matters is the rank, as in App Store rankings. avoid: The value gaps between ranks matter. - box (, Box / violin plot, 박스 플롯, advanced): Distribution summary by group (quartiles, median, outliers). encoding: group, value. use: Distribution and outliers together, such as response time by API. avoid: The audience is not used to quartiles (a beeswarm is easier). - parallel (, Parallel coordinates, 평행 좌표, advanced): Several numeric metrics, each on its own axis, compared as one line per row. encoding: label?. use: Comparing 4 to 8 metrics at once, such as product specs. avoid: The audience sees it for the first time (it needs explaining). - candlestick (, Candlestick chart, 캔들스틱, advanced): Open, high, low and close for each period in one candle. encoding: x, open, high, low, close, volume?. use: Stocks, exchange rates or coins, where the swing within each period matters. avoid: A trend with only one value (a line chart is cleaner). - segmented (, Segmented bar, 비율 막대, basic): One whole split into a bar by share, with a list. encoding: label, value. use: Showing the mix in one line inside a card (2 to 6 items). avoid: Comparing similar values, or many items (a bar chart is more accurate). - skyline (, Skyline, 스카이라인, intermediate): Stacked volume per period as blocks, with a smaller outcome in the same unit standing in front. encoding: x, y[], series?, front?[]. use: 7 to 40 periods of stacked volume and a smaller outcome in the same unit (failures, retries), as the lead card of a dashboard. avoid: Negative values, precise value comparison (bars are more accurate), or two values in different units (split the chart and link it with syncId). - histogram (, Histogram, 히스토그램, intermediate): Distribution of raw samples with its tail and the share past a limit. encoding: value?, group?, x0?, x1?, count?. use: 30 or more raw samples, such as request latency, where the tail and the share past a limit matter. avoid: Comparing categories (use bars), or fewer than 10 samples (a beeswarm fits better). - scatter (, Scatter plot, 산점도, basic): How two numbers relate, one dot per item, colored by series. encoding: x, y, series?, label?. use: How two numeric values relate, such as cost and latency per request, with up to 4 series. avoid: x is time (a line works better), or there are more than 50,000 dots. Bundle size per chart (Brotli by size-limit, one import including the shared core, React excluded): PieChart 13.87 KB, DonutChart 13.89 KB, FunnelChart 12.26 KB, WaffleChart 12.47 KB, Treemap 12.84 KB, SunburstChart 13.2 KB, WaterfallChart 13.44 KB, ParetoChart 13.68 KB, MarimekkoChart 13.09 KB, Heatmap 14.16 KB, RadarChart 13.69 KB, BubbleChart 16.13 KB, LineChart 25.97 KB, AreaChart 25.97 KB, StreamGraph 16.26 KB, BarChart 20.45 KB, RadialBarChart 11.85 KB, GaugeChart 12.04 KB, BulletChart 12.63 KB, Sparkline 14.51 KB, SlopeChart 12.75 KB, DumbbellChart 12.25 KB, LollipopChart 13.11 KB, BeeswarmChart 14.08 KB, RidgelineChart 12.97 KB, SankeyChart 13.5 KB, ChordChart 12.48 KB, CalendarHeatmap 15.01 KB, BumpChart 14.49 KB, BoxPlot 14.37 KB, ParallelCoordinates 13.59 KB, CandlestickChart 20.12 KB, SegmentedBar 12.47 KB, SkylineChart 18.67 KB, HistogramChart 18.3 KB, ScatterChart 18.91 KB, StatCard 15.13 KB, LiveLineChart 13.61 KB ## Docs - [Full reference](llms-full.txt): this file plus the agent workflow, a chart picking table, and every chart's encoding channels, options and example spec - [README](https://github.com/Junhan2/ztd-charts/blob/main/README.md): what it is, install, quick start, the 36 charts, AI setup and the packages - [Guide](https://github.com/Junhan2/ztd-charts/blob/main/docs/guide.md): common props, cards and grid, theme tokens, animation, accessibility, data sources, JSON spec, CLI and MCP setup - [Agent skill](https://github.com/Junhan2/ztd-charts/blob/main/skills/ztd-charts/SKILL.md): steps for an agent to pick a chart, write and validate a spec, and preview it - [JSON Schema](https://unpkg.com/ztd-charts/schema/chart-spec.schema.json): the spec schema, draft 2020-12 ## Optional - [Chart catalog](https://github.com/Junhan2/ztd-charts/blob/main/docs/catalog.md): why each chart was chosen - [README in Korean](https://github.com/Junhan2/ztd-charts/blob/main/README.ko.md) · [Guide in Korean](https://github.com/Junhan2/ztd-charts/blob/main/docs/guide.ko.md) - [License](https://github.com/Junhan2/ztd-charts/blob/main/LICENSE): MIT