Choropleth Chart
Region intensity map. Default and Motion variants.
Examples
Installation
Default is a ready-made wrapper from the registry. Motion is the composable engine at @cronus-ui/ui/charts (peer visx + motion).
npx cronus-ui add choropleth-chart
import { ChoroplethChart } from "@cronus-ui/ui";
Usage
Motion expects a GeoJSON FeatureCollection (Polygon / MultiPolygon). Default is a region grid (`ChoroplethRegion[]`), not a map. Fetch world GeoJSON at runtime — there is no bundled topology.
import {ChoroplethChart,ChoroplethFeatureComponent,ChoroplethGraticule,ChoroplethTooltip,} from "@cronus-ui/ui/charts";<ChoroplethChart data={world} aspectRatio="16 / 9" zoomEnabled><ChoroplethGraticule /><ChoroplethFeatureComponentfill="var(--chart-scale-03)"stroke="var(--chart-background)"strokeWidth={0.5}/><ChoroplethTooltip /></ChoroplethChart>
Components
Motion API — compose these under the chart root. Default wrapper props are in Default API below.
ChoroplethChart
Mercator projection, optional zoom/pan, context for children.
| Prop | Type | Default | Description |
|---|---|---|---|
data* | FeatureCollection | — | GeoJSON features. |
margin | `Partial<{ top, right, bottom, left }>` | { top: 0, right: 0, bottom: 0, left: 0 } | Plot margins. |
animationDuration | number | 800 | Enter duration in ms. |
aspectRatio | string | "16 / 9" | CSS aspect ratio. |
scale | number | — | Projection scale. Auto from width when omitted. |
center | [number, number] | [0, 20] | Center [longitude, latitude]. |
zoomEnabled | boolean | false | Zoom and pan. |
zoomMin | number | 0.5 | Minimum zoom scale. |
zoomMax | number | 4 | Maximum zoom scale. |
ChoroplethFeatureComponent
Country/region paths with hover dim and optional pattern fills.
| Prop | Type | Default | Description |
|---|---|---|---|
fill | string | — | Solid fill for every feature (overrides getFeatureColor). |
stroke | string | var(--chart-background) | Border color. |
strokeWidth | number | 0.5 | Border width. |
fadedOpacity | number | 0.4 | Opacity when another feature is hovered. |
getFeatureColor | (feature, index) => string | — | Per-feature fill. |
patterns | ReactNode | — | visx pattern definitions. |
getFeaturePattern | (feature, index) => string | null | — | Pattern id for a feature. |
ChoroplethGraticule
Latitude / longitude grid.
| Prop | Type | Default | Description |
|---|---|---|---|
stroke | string | rgba(255,255,255,0.1) | Line color. |
strokeWidth | number | 0.5 | Line width. |
step | [number, number] | [10, 10] | Step [longitude, latitude] in degrees. |
ChoroplethTooltip
Pointer-following tooltip. Defaults to properties.name.
| Prop | Type | Default | Description |
|---|---|---|---|
content | (props) => ReactNode | — | Custom renderer. |
getFeatureName | (feature, index) => string | — | Name getter. |
getFeatureValue | (feature, index) => number | — | Value getter. |
valueLabel | string | "Value" | Label for the value row. |
formatValue | (value: number) => string | — | Value formatter. |
Zoom
zoomEnabled turns on wheel/drag. useChoroplethZoom() exposes the visx Zoom instance so you can render +/- buttons outside the SVG.
const { zoom } = useChoroplethZoom();<Button onClick={() => zoom?.scale({ scaleX: 1.2, scaleY: 1.2 })}>+</Button>
Color by value
Pass getFeatureColor to bin regions onto --chart-scale-01…05. Keep stroke on --chart-background so borders stay visible.
<ChoroplethFeatureComponentstroke="var(--chart-background)"strokeWidth={0.5}getFeatureColor={(feature) => {const value = Number(feature.properties.value ?? 0);if (value > 80) return "var(--chart-scale-05)";if (value > 40) return "var(--chart-scale-03)";return "var(--chart-scale-01)";}}/>
Data format
Load GeoJSON yourself (for example a world FeatureCollection). Convert TopoJSON with topojson-client if that is your source format — it is not a Cronus dependency.
import type { FeatureCollection, Geometry } from "geojson";interface FeatureCollection {type: "FeatureCollection";features: Array<{type: "Feature";geometry: Geometry;properties: { name?: string; id?: string | number; [key: string]: unknown };}>;}// Default wrapper (not Motion) uses a region list instead:type ChoroplethRegion = { id: string; name: string; value: number };
Theming
Motion charts read `--chart-*` aliases that map onto Cronus semantic tokens (`--cronus-chart-1`…`--cronus-chart-5`, `--cronus-border`, `--cronus-fg`, surfaces). Override the aliases or the tokens — never palette scales (`bg-zinc-900`). Default wrappers use `ChartConfig` with `var(--cronus-chart-*)` / `var(--cronus-primary)`. Sequential bins use `--chart-scale-01`…`--chart-scale-05` (01 = lowest). Empty regions typically use `var(--muted)` or a mix of `--cronus-surface-base`.
Full token reference: Theming.
Dependencies
Default needs the recharts peer. Motion needs visx (and sometimes d3) as optional peers — install only what this chart uses.
bun add recharts
bun add @visx/geo @visx/responsive @visx/zoom d3-geo motion
Default API
Generated from the Default wrapper's exported types. Motion subcomponents are documented above.
ChoroplethChartProps
Extends HTMLAttributes<HTMLDivElement>
| Prop | Type | Default | Description |
|---|---|---|---|
data | ChoroplethRegion[] | CHOROPLETH_DEMO | — |