KQ-1318 · REGION/MAP
Region Map
A choropleth of invented regions with the numbers behind every colour. Picking a region leans the map toward it: the camera — centre and scale written into the SVG viewBox — glides on glide to frame it, the region lifts above its neighbours on snap with a flat shadow while the rest dim, and the side panel swaps the ranking for the region's numbers and trend, with Previous and Next travelling region to region by rank. The legend is a slider you scrub: a bracket follows the finger 1:1 and lights only the regions inside the band, then springs onto the class under it on snap with the throw's velocity. The map is a listbox where arrows move to the nearest region in that direction, Enter picks and Escape leans out; the legend takes arrows, Home, End and Escape.
all regions · riders · top: Harrow Fen
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/region-map
Props
- zoom
- number
- default 2.5
- How far the map leans in on a picked region, from 1 (it stays put and only highlights) to 4.
- legend
- "steps" | "ramp"
- default "steps"
- Stepped classes or a continuous ramp — for the fills, the legend, and how a scrubbed band snaps (to a class, or wherever it is let go).
- scheme
- "cobalt" | "signal" | "heat" | "diverging"
- default "cobalt"
- The colour scheme: one hue, a warm heat ramp, or a diverging pair around zero for changes. Fills are pigment mixed into the card colour, so both themes read.
- regions
- RegionMapRegion[]
- default defaultRegionMapRegions
- The regions as SVG paths in the map's viewBox: id, name, d, and an optional box ([x, y, width, height], measured from the path when omitted) and label point. The default is fourteen regions generated once from seeded points.
- viewBox
- [number, number, number, number]
- default defaultRegionMapViewBox
- The map's extent: what the camera shows when nothing is picked.
- stats
- RegionMapStat[]
- default defaultRegionMapStats
- What is measured: id, label, kind (count, money, percent as a fraction, or number), an optional unit word and signed for changes. Each becomes a metric option and a row in the details panel.
- data
- RegionMapDatum[]
- default defaultRegionMapData
- One datum per region: its values per stat id and optional trends (recent readings, oldest first) drawn in the details panel. Regions without a datum read as no data.
- metric / defaultMetric
- string
- default the first stat
- The stat id the map is coloured and ranked by. Controlled or uncontrolled.
- onMetricChange
- (metric: string) => void
- default —
- Fires from the metric switch with the new stat id. A band is cleared with it, since it was in the old metric's units.
- value / defaultValue
- string | null
- default null
- The picked region the map leans toward, or null for the whole map. Controlled or uncontrolled; a host change moves the camera the same way a click does.
- onValueChange
- (region: string | null) => void
- default —
- Fires from the click, key or button that picked a region, or with null when the map leans out.
- band / defaultBand
- [number, number] | null
- default null
- The [low, high] values the legend highlights; regions outside it fade back. Controlled or uncontrolled.
- onBandChange
- (band: [number, number] | null) => void
- default —
- Fires when a scrub settles, a tap or key moves the band, or it is cleared.
- steps
- number
- default 5
- Classes in the stepped legend, 3 to 7, laid on round numbers that hold every value.
- format
- (value: number, stat: RegionMapStat) => string
- default —
- How a value reads in the tooltip, the panel and the spoken text. Defaults to the stat's kind in locale.
- locale
- string
- default "en-US"
- The locale for numbers and money.
- currency
- string
- default "USD"
- The currency for money stats.
- status
- "ready" | "loading" | "error"
- default "ready"
- Whether the numbers have arrived: loading shows a skeleton, error a retry over the map.
- onRetry
- () => void
- default —
- Try again was pressed after the numbers failed to load.
- title
- string
- default "Regions"
- The map's heading.
- subtitle
- string
- default —
- A quieter line under the heading.
- label
- string
- default —
- The map's accessible name. Defaults to the title.
- maxHeight
- number
- default 580
- The tallest the surface grows, in px; it scrolls inside itself past that (the phone layout does).
- sound
- boolean
- default false
- Play a swish whenever the camera moves, panned to the region, and a plip as a scrubbed band crosses into a new class.
- disabled
- boolean
- default false
- Shows the map and its numbers but refuses picks, bands and metric changes.
- className
- string
- default —
- Classes for the outer panel.
| Prop | Type | Default | Description |
|---|---|---|---|
| zoom | number | 2.5 | How far the map leans in on a picked region, from 1 (it stays put and only highlights) to 4. |
| legend | "steps" | "ramp" | "steps" | Stepped classes or a continuous ramp — for the fills, the legend, and how a scrubbed band snaps (to a class, or wherever it is let go). |
| scheme | "cobalt" | "signal" | "heat" | "diverging" | "cobalt" | The colour scheme: one hue, a warm heat ramp, or a diverging pair around zero for changes. Fills are pigment mixed into the card colour, so both themes read. |
| regions | RegionMapRegion[] | defaultRegionMapRegions | The regions as SVG paths in the map's viewBox: id, name, d, and an optional box ([x, y, width, height], measured from the path when omitted) and label point. The default is fourteen regions generated once from seeded points. |
| viewBox | [number, number, number, number] | defaultRegionMapViewBox | The map's extent: what the camera shows when nothing is picked. |
| stats | RegionMapStat[] | defaultRegionMapStats | What is measured: id, label, kind (count, money, percent as a fraction, or number), an optional unit word and signed for changes. Each becomes a metric option and a row in the details panel. |
| data | RegionMapDatum[] | defaultRegionMapData | One datum per region: its values per stat id and optional trends (recent readings, oldest first) drawn in the details panel. Regions without a datum read as no data. |
| metric / defaultMetric | string | the first stat | The stat id the map is coloured and ranked by. Controlled or uncontrolled. |
| onMetricChange | (metric: string) => void | — | Fires from the metric switch with the new stat id. A band is cleared with it, since it was in the old metric's units. |
| value / defaultValue | string | null | null | The picked region the map leans toward, or null for the whole map. Controlled or uncontrolled; a host change moves the camera the same way a click does. |
| onValueChange | (region: string | null) => void | — | Fires from the click, key or button that picked a region, or with null when the map leans out. |
| band / defaultBand | [number, number] | null | null | The [low, high] values the legend highlights; regions outside it fade back. Controlled or uncontrolled. |
| onBandChange | (band: [number, number] | null) => void | — | Fires when a scrub settles, a tap or key moves the band, or it is cleared. |
| steps | number | 5 | Classes in the stepped legend, 3 to 7, laid on round numbers that hold every value. |
| format | (value: number, stat: RegionMapStat) => string | — | How a value reads in the tooltip, the panel and the spoken text. Defaults to the stat's kind in locale. |
| locale | string | "en-US" | The locale for numbers and money. |
| currency | string | "USD" | The currency for money stats. |
| status | "ready" | "loading" | "error" | "ready" | Whether the numbers have arrived: loading shows a skeleton, error a retry over the map. |
| onRetry | () => void | — | Try again was pressed after the numbers failed to load. |
| title | string | "Regions" | The map's heading. |
| subtitle | string | — | A quieter line under the heading. |
| label | string | — | The map's accessible name. Defaults to the title. |
| maxHeight | number | 580 | The tallest the surface grows, in px; it scrolls inside itself past that (the phone layout does). |
| sound | boolean | false | Play a swish whenever the camera moves, panned to the region, and a plip as a scrubbed band crosses into a new class. |
| disabled | boolean | false | Shows the map and its numbers but refuses picks, bands and metric changes. |
| className | string | — | Classes for the outer panel. |