import { ChoroplethMap } from "semiotic/geo"
ChoroplethMap colors geographic regions by a data value, producing the classic thematic map. Pass "world-110m" as theareas prop to load a built-in world map, or bring your own GeoJSON. Join external data via mergeData and get automatic projection fitting, sequential color encoding, and hover tooltips.
Quick Start
The fastest way to a world choropleth: use the built-in"world-110m" reference, join your data by ISO country ID, and point valueAccessor at the merged field.
JSX
import { ChoroplethMap, mergeData, resolveReferenceGeography } from "semiotic/geo" // 1. Load built-in world map (Natural Earth 110m via topojson-client) const worldFeatures = await resolveReferenceGeography("world-110m") // 2. Join your data by ISO 3166 numeric ID const areas = mergeData(worldFeatures, countryGDP, { featureKey: "id", // world-atlas uses ISO numeric IDs dataKey: "id" // your data's matching key }) // 3. Render <ChoroplethMap areas={areas} valueAccessor="gdpPerCapita" colorScheme="viridis" projection="equalEarth" tooltip />
Or use the string shorthand directly — areas="world-110m"resolves the reference automatically (but won't have your data merged in).
Reference Geography
Built-in reference maps useNatural Earthdata from the world-atlas npm package, converted from TopoJSON to GeoJSON at runtime via topojson-client. Results are cached — the conversion only happens once.
| Reference | Content | Size (gzipped) | Join Key |
|---|
"world-110m" | 177 countries | ~24 KB | id = ISO 3166 numeric |
"world-50m" | 177 countries (higher detail) | ~100 KB | id = ISO 3166 numeric |
"land-110m" | Land mass outline | ~10 KB | n/a |
"land-50m" | Land mass outline (higher detail) | ~40 KB | n/a |
Joining Data
mergeData(features, data, { featureKey, dataKey })performs a key-based join — each row in your data array is merged into the matching feature's properties. Supports nested key paths like "properties.iso_a3".
TS
import { mergeData, resolveReferenceGeography } from "semiotic/geo" const world = await resolveReferenceGeography("world-110m") // Join by ISO 3166 numeric ID (default for world-atlas) const byNumericId = mergeData(world, data, { featureKey: "id", dataKey: "country_id" }) // Or join by country name if your features have it const byName = mergeData(world, data, { featureKey: "properties.name", dataKey: "country_name" })
Examples
Color Schemes
Four built-in sequential schemes: "blues","reds", "greens", and "viridis".
Loading world map...
Graticule Grid
Enable graticule to overlay a latitude/longitude grid for geographic context.
Loading world map...
Props
| Prop | Type | Required | Default | Description |
|---|
areas | GeoJSON.Feature[] | "world-110m" | "world-50m" | "land-110m" | "land-50m" | Yes | — | GeoJSON features or a reference string. Reference strings load built-in Natural Earth data via dynamic import. |
valueAccessor | string | function | Yes | — | Field name or function to extract the numeric value for color encoding from each feature's properties. |
colorScheme | "blues" | "reds" | "greens" | "viridis" | — | "blues" | Sequential color scheme for the choropleth fill. |
projection | string | object | function | — | "equalEarth" | Projection name ("mercator", "equalEarth", "naturalEarth", etc.), config object, or d3 projection function. |
projectionExtent | [[number, number], [number, number]] | — | — | Geographic bounding box [[west, south], [east, north]] to constrain the projection fit. |
graticule | boolean | object | — | false | Show a latitude/longitude grid. Pass true or a config { step, stroke, strokeWidth }. |
tooltip | boolean | function | object | — | — | Tooltip configuration. true for default, function for custom render, or config object. |
showLegend | boolean | — | true | Show a color legend. |
legendInteraction | "none" | "highlight" | "isolate" | — | "none" | How legend items interact with the chart on hover/click. |
annotations | array | — | — | Array of annotation objects to overlay on the map. |
title | string | — | — | Chart title displayed at the top. |
width | number | — | 600 | Chart width in pixels. |
height | number | — | 400 | Chart height in pixels. |
margin | object | — | { top: 10, bottom: 10, left: 10, right: 10 } | Margin around the chart area. |
selection | object | — | — | Selection config for LinkedCharts integration. |
linkedHover | object | — | — | Linked hover config for cross-chart highlighting. |
onObservation | function | — | — | Callback for chart observation events (hover, click). |
frameProps | object | — | — | Additional StreamGeoFrame props for advanced customization. |
Graduating to the Frame
When you need full control — custom area styles, mixed points and areas, streaming, zoom — graduate toStreamGeoFrame.
Chart (simple)
JSX
import { ChoroplethMap } from "semiotic/geo" <ChoroplethMap areas="world-110m" valueAccessor="population" colorScheme="blues" tooltip />
Frame (full control)
JSX
import { StreamGeoFrame } from "semiotic/geo" <StreamGeoFrame projection="equalEarth" areas={features} areaStyle={(d) => ({ fill: colorScale(d.properties.population), stroke: "#fff", strokeWidth: 0.5, })} enableHover tooltipContent={(d) => <CustomTooltip data={d} />} size={[600, 400]} />