Skip to content
Charts

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).

bash
npx cronus-ui add choropleth-chart
tsx
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.

tsx
import {
ChoroplethChart,
ChoroplethFeatureComponent,
ChoroplethGraticule,
ChoroplethTooltip,
} from "@cronus-ui/ui/charts";
<ChoroplethChart data={world} aspectRatio="16 / 9" zoomEnabled>
<ChoroplethGraticule />
<ChoroplethFeatureComponent
fill="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.

Skip ChoroplethChartProps props table
PropTypeDefaultDescription
data*
FeatureCollection—GeoJSON features.
margin
`Partial<{ top, right, bottom, left }>`{ top: 0, right: 0, bottom: 0, left: 0 }Plot margins.
animationDuration
number800Enter 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
booleanfalseZoom and pan.
zoomMin
number0.5Minimum zoom scale.
zoomMax
number4Maximum zoom scale.

ChoroplethFeatureComponent

Country/region paths with hover dim and optional pattern fills.

Skip ChoroplethFeatureComponentProps props table
PropTypeDefaultDescription
fill
string—Solid fill for every feature (overrides getFeatureColor).
stroke
stringvar(--chart-background)Border color.
strokeWidth
number0.5Border width.
fadedOpacity
number0.4Opacity 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.

Skip ChoroplethGraticuleProps props table
PropTypeDefaultDescription
stroke
stringrgba(255,255,255,0.1)Line color.
strokeWidth
number0.5Line width.
step
[number, number][10, 10]Step [longitude, latitude] in degrees.

ChoroplethTooltip

Pointer-following tooltip. Defaults to properties.name.

Skip ChoroplethTooltipProps props table
PropTypeDefaultDescription
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.

tsx
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.

tsx
<ChoroplethFeatureComponent
stroke="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.

ts
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.

bash
bun add recharts
bash
bun add @visx/geo @visx/responsive @visx/zoom d3-geo motion

.cronus

The same component declared in Cronus. Emitted at build time from the audit fixtures — the kernel renders it as HTML with no React.

PortedParity: MatchGeometry 1/1Pixel diff 0 pxLogic 1/1Parity scoreboard
default.cronus
app "audit-fixtures" {
  port 5176
}

style {
  preset aurora
  theme dark
}

component ChoroplethChartDefault layout:inline style:choropleth-chart {
  label "Regions"
  text "Northwest"
  text "Northeast"
  text "Central"
  text "Southeast"
}

page "/audit/choropleth-chart/default" type:custom {
  use ChoroplethChartDefault
}

Default API

Generated from the Default wrapper's exported types. Motion subcomponents are documented above.

ChoroplethChartProps

Extends HTMLAttributes<HTMLDivElement>

Skip ChoroplethChartProps props table
PropTypeDefaultDescription
data
ChoroplethRegion[]CHOROPLETH_DEMO—
className
string—Additional class names merged onto the root.
children
ReactNode—Contents of the component.
id
string—DOM id of the root element.