ComponentsData display

Pin map

Markers on a projected sheet — stores, field jobs, vehicles, live visitors — without a tile provider or API key. Pins sit in Web Mercator inside your bounds over a quiet coordinate grid with a scale bar; pass a backdrop to lay them over your own static map. Selection syncs with a list, and arrow keys move to the nearest pin in that direction.

Web Mercator · roving tabindex components/pin-map.tsxtheme · material · accent · density · font

Moda

52 orders today · open until 22:00

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { PinMap } from "@vamos-ui/react";

<PinMap aria-label="Stores" pins={stores.map((s) => ({ id: s.id, lat: s.lat, lng: s.lng, label: s.name }))}
  selectedId={selected} onSelectedIdChange={setSelected} />

Keyboard: Tab enters on the selected (or first) pin, arrows go to the nearest pin in that direction, Home/End jump, Enter/Space toggles selection, Escape clears.

Not a slippy map: no panning or zoom. For street-level navigation use a map provider and keep PinMap for overviews and placeholders.

Examples

Dispatch with a synced list (ops)

Status tones, a pulse for vehicles en route, icons in the markers, and selection shared with the list.

Measure for curtains, Üsküdar

Selin Öztürk · En route · ETA 10:38

Live visitors (analytics)

variant="bubble" sizes by value (area, not radius); children overlay the map.

Right now

177

Labels and dots

Without bounds the map fits every pin; showLabels for a handful of sites.

API

PinMap

PropTypeDefault
pins
{ id, lat, lng, label, description?, tone?, value?, pulse?, icon? }. label is the accessible name.
MapPin[]—
aria-label
Required. What the map shows.
string—
bounds
Visible area. Omit to fit every pin. Always widened to the aspect ratio so shapes stay true.
{ north, south, west, east }—
aspectRatio
Width ÷ height.
number16 / 10
variant
Markers, small dots or value-sized bubbles.
"pin" | "dot" | "bubble""pin"
selectedId / defaultSelectedId / onSelectedIdChange
Selection (controlled or not). Clicking a selected pin clears it; Escape too.
string | null—
callout
Card above the selected pin. Default: label + description; it also becomes the pin's accessible description.
false | (pin) => ReactNode—
showLabels
Labels beside every marker.
boolean—
backdrop
Your own layer under the pins (a static map image, district outlines).
ReactNode—
bare
Hide coordinate ticks and the scale bar.
boolean—
children
Overlay content (legend, totals), positioned by you.
ReactNode—