Markers
Markers are named pins on the map with optional colors, icons, labels, tooltips, and popups.
Basic Usage
{
"markers": {
"cafe": {
"coordinates": [-73.98, 40.75],
"color": "#e74c3c",
"icon": "coffee",
"tooltip": "Blue Bottle ยท Midtown",
"popup": {
"title": "Blue Bottle Coffee",
"description": "Specialty coffee roaster"
}
},
"park": {
"coordinates": [-73.97, 40.76],
"color": "#22c55e",
"icon": "tree-pine",
"tooltip": "Central Park ยท Manhattan"
}
}
}Properties
| Property | Type | Required | Description |
|---|---|---|---|
coordinates | [lng, lat] | Yes | Marker position |
color | string | No | Marker color (hex) |
icon | string | No | Built-in icon name in kebab-case (see below) |
label | string | No | Text displayed below the marker |
tooltip | string | No | Short text shown on hover |
popup | string | PopupSpec | No | Content shown when marker is clicked |
draggable | boolean | No | Whether the marker can be dragged |
Marker Styles
Markers come in two visual styles:
- Dot โ default when no
iconis set. A colored circle with a white border. - Icon โ when
iconis set. A colored circle with a white icon inside.
{
"markers": {
"plain": { "coordinates": [0, 0], "color": "#e74c3c" },
"with-icon": { "coordinates": [1, 0], "color": "#3498db", "icon": "star" }
}
}Built-in Icons
json-maps ships with 21 built-in icons (subset of Lucide as inline SVGs). No icon library dependency required.
| Icon | Name | Good for |
|---|---|---|
| ๐ | map-pin | Generic location |
| โญ | star | Highlights, favorites |
| โค๏ธ | heart | Liked places |
| ๐ฉ | flag | Start/end points |
| โ | coffee | Cafes |
| ๐ด | utensils | Restaurants |
| ๐จ | hotel | Hotels, lodging |
| ๐ข | building-2 | Offices, buildings |
| ๐ฒ | tree-pine | Parks, nature |
| โฐ๏ธ | mountain | Mountains, hiking |
| โ๏ธ | plane | Airports |
| ๐ | train | Train stations |
| ๐ | car | Parking, driving |
| ๐ | bus | Bus stops |
| ๐ | truck | Logistics, delivery |
| ๐ข | ship | Ports, harbors |
| โช | church | Religious sites |
| ๐ | shopping-cart | Shopping |
| ๐ท | camera | Photo spots, landmarks |
| ๐๏ธ | landmark | Monuments, government |
| โบ | tent | Camping |
Custom Icons
Need icons beyond the built-in set? Override the Marker component with your own that uses any icon library. See Component Slots.
import { MapRenderer } from "json-maps";
import { DynamicIcon } from "lucide-react/dynamic"; // or any icon lib
function CustomMarker({ marker, color }) {
return (
<div style={{ background: color, borderRadius: "50%", padding: 6 }}>
<DynamicIcon name={marker.icon} size={16} color="white" />
</div>
);
}
<MapRenderer spec={spec} components={{ Marker: CustomMarker }} />Tooltip vs Popup
- Tooltip โ appears on hover, disappears on mouse leave. Short, one-line text.
- Popup โ appears on click. Can contain title, description, and image.
Popup Formats
The popup field accepts either a simple string or a rich object:
Simple string:
{ "popup": "A brief description" }Rich popup with title, description, and image:
{
"popup": {
"title": "Eiffel Tower",
"description": "330m iron lattice tower on the Champ de Mars",
"image": "https://example.com/eiffel.jpg"
}
}Events
Marker events are handled via props on MapRenderer. See Events for details.
<MapRenderer
spec={spec}
onMarkerClick={(id, coords) => console.log(id, coords)}
onMarkerDragEnd={(id, coords) => console.log(id, coords)}
/>Custom Markers
You can replace the default marker component with your own. See Component Slots.
Why Named Map?
Markers use a named map ({ "cafe": {...} }) instead of an array. This makes it easy to:
- Reference individual markers by key
- Update or remove a specific marker via JSON patches
- Stream marker additions without replacing the whole array