Skip to content
Generative UIChartMenu

Chart

Bar, line, area and proportion charts in a color-blind aware categorical palette, with dashes and end markers on lines, direct labels, a tooltip on hover and focus, and a table for screen readers. No chart library.

Three latency series told apart by hue, dashes and end markers, then a column chart with one run emphasized.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/chart.json

Usage

tsx
import { Chart } from "@/components/ui/chatcn/chart"

<Chart
  type="line"
  title="p95 latency since the connection pool change"
  data={rows}
  xKey="day"
  series={[{ key: "api", label: "API" }, { key: "edge", label: "Edge" }]}
  unit="ms"
/>

Data is an array of rows. xKey names the category field (default label) and series the value fields (default value). Values format with valueFormat, unit and currency, or your own format.

Examples

Bar, stacked, area and proportion

Horizontal bars suit long names and rankings and carry their value at the tip. Stacks separate segments with a 2 px gap in the surface color. The proportion bar replaces a pie: one bar, labelled rows with percentages, and nothing to compare by angle.

Horizontal bars with values at the tips, hatched stacks, an area wash and the proportion bar that replaces a pie.

Streaming points

Pass expectedCount and domain while points stream in. Slots and the axis are reserved, so earlier points never move or rescale. Each new mark reveals once from its baseline.

Points arrive one at a time into reserved slots and a fixed domain, so nothing already drawn moves.

Loading, empty and error

Static skeletons at the final size, an empty result and a spec that failed to render.

Encodings

SeriesBars and areasLines
1--chatcn-chart-1 (blue)Blue, solid, circle
2--chatcn-chart-2 (amber)Amber, solid, square
3--chatcn-chart-3 (teal)Teal, dashed, diamond
4--chatcn-chart-4 (magenta)Magenta, dotted, triangle
5--chatcn-chart-5 (orange)Orange, solid, circle
6--chatcn-chart-6 (violet)Violet, dashed, square

Lines label their ends directly when the labels have room and show a legend only when they would collide. Bars show a legend from two series up. highlight keeps one category at full strength and steps the rest back. The hues are picked to stay apart for the common color blindness types; override the six variables to use your brand palette.

Props

PropTypeNotes
type"bar" | "line" | "area" | "proportion"Default bar
dataChartDatum[]Rows. Non-numeric values read as gaps
xKeystringCategory field. Default label
series(string | { key, label? })[]Up to six. Default ["value"]
layout"vertical" | "horizontal"Bars only
stackedbooleanStack bar series
heightnumberPlot height in px. Default 200
valueFormat, unit, currency, formatValue formatting. Ticks compact from 1,000 up
domain[number, number]Fixed value range, for streaming
expectedCountnumberSlots reserved while streaming
valueLabels"auto" | "all" | "none"Column cap labels. auto labels when all fit
highlightstringCategory to keep in ink
summarystringScreen reader summary. Generated when omitted
loading, streaming, error, emptyStates
view, defaultView, onViewChange"chart" | "table"Controlled or uncontrolled table toggle
variant"card" | "plain"Default card

ProportionBar is exported on its own for meters and breakdowns.

Keyboard

KeyAction
TabFocus the plot (one stop), then the table toggle
Arrow keysMove between categories and show their values
Home / EndFirst or last category
EscapeHide the tooltip

Accessibility

  • Every chart renders a real table: hidden visually by default, shown with the table toggle. The plot is described by it and labelled with a generated summary of range and peaks.
  • Series never depend on telling grays apart: texture, dashes and marker shapes carry identity too, which also survives grayscale printing.
  • The tooltip mirrors what the table holds, so it enhances and never gates.

Motion

  • Marks reveal once with a clip-path from their baseline, 280 ms ease-out, lines draw left to right in 300 ms. Re-renders never replay; streamed points reveal on their own.
  • The tooltip fades in once in 125 ms, then follows the pointer without animation. Keyboard navigation is instant.
  • Reduced motion swaps every reveal for a 150 ms fade.