Map

pro

Map wraps MapLibre with markers, popups, routes, arcs, and point clustering, themed to match the rest of the UI.

Installation

Add this component with the NateUI CLI.

npx nateui@latest add Map

Examples

Static Preview

Popups & Labels

Controls

Cluster Layer

Controlled Viewport

40.71, -74.01 · zoom 11.0

API

Map

PropDescriptionTypeDefault
childrenMarkers, popups, routes, arcs, and cluster layers.ReactNode—
themeTile style to use.'light' | 'dark'app's ConfigProvider mode
stylesOverride the default tile style URL per theme.{ light?: MapStyleOption; dark?: MapStyleOption }OpenFreeMap positron/dark
viewportControlled camera. Pair with onViewportChange (see Controlled Viewport).Partial<MapViewport>—
onViewportChangeCalled on pan/zoom/rotate with the new camera state.(viewport: MapViewport) => void—
loadingShows a centered spinner overlay.booleanfalse
refExposes the underlying maplibregl.Map instance.Ref<MapRef | null>—
classNameClass names applied to the map's root element.string—
centerInitial camera center (uncontrolled).LngLatTuple—
zoomInitial zoom level (uncontrolled).number—
bearingInitial map rotation, in degrees (uncontrolled).number0
pitchInitial camera tilt, in degrees (uncontrolled).number0
interactiveDisables all pan/zoom/rotate gestures when false.booleantrue
attributionControlShows the map data attribution badge.booleantrue
...mapOptionsThe rest of MapLibre's own MapOptions — see MapLibre's docs.Omit<maplibregl.MapOptions, 'container' | 'style'>—

Map.Marker

PropDescriptionTypeDefault
longitudeMarker position.number—
latitudeMarker position.number—
childrenMarker visual and any attached Map.MarkerPopup / Map.MarkerTooltip / Map.MarkerLabel.ReactNode—
onClickFired on marker click.(event: MouseEvent) => void—
onMouseEnter / onMouseLeaveFired on hover.(event: MouseEvent) => void—
onDragStart / onDrag / onDragEndFired while dragging, when draggable is set.(lngLat: { lng: number; lat: number }) => void—
...markerOptionsThe rest of MapLibre's own MarkerOptions (draggable, offset, rotation, anchor, color, …).Omit<maplibregl.MarkerOptions, 'element'>—

Map.MarkerContent

The default pin visual — a small primary-colored dot. Not required; Map.Marker's children accepts any node.

PropDescriptionTypeDefault
childrenContent rendered inside the dot.ReactNode—
classNameClass names applied to the dot.string—

Map.MarkerPopup

Click-to-open popup attached to a marker. Must be rendered inside Map.Marker.

PropDescriptionTypeDefault
childrenPopup content.ReactNode—
closeButtonShows a close button in the corner.booleanfalse
classNameClass names applied to the popup body.string—
...popupOptionsThe rest of MapLibre's own PopupOptions (offset, maxWidth, anchor, …).Omit<maplibregl.PopupOptions, 'closeButton'>—

Map.MarkerTooltip

Hover-to-show tooltip attached to a marker. Must be rendered inside Map.Marker.

PropDescriptionTypeDefault
childrenTooltip content.ReactNode—
classNameClass names applied to the tooltip body.string—
...popupOptionsThe rest of MapLibre's own PopupOptions, minus closeButton and closeOnClick.Omit<maplibregl.PopupOptions, 'closeButton' | 'closeOnClick'>—

Map.MarkerLabel

Small always-visible caption positioned above or below a marker.

PropDescriptionTypeDefault
childrenLabel content.ReactNode—
positionSide of the marker the label sits on.'top' | 'bottom''top'
classNameClass names applied to the label.string—

Map.Popup

A standalone popup at its own coordinate, not attached to a marker.

PropDescriptionTypeDefault
longitudePopup position.number—
latitudePopup position.number—
childrenPopup content.ReactNode—
closeButtonShows a close button in the corner.booleanfalse
onCloseCalled when the popup closes.() => void—
classNameClass names applied to the popup body.string—
...popupOptionsThe rest of MapLibre's own PopupOptions, minus closeButton.Omit<maplibregl.PopupOptions, 'closeButton'>—

Map.Controls

Floating zoom / compass / locate / fullscreen button cluster.

PropDescriptionTypeDefault
positionCorner of the map the cluster docks to.'top-left' | 'top-right' | 'bottom-left' | 'bottom-right''bottom-right'
showZoomShows zoom in/out buttons.booleantrue
showCompassShows a button that resets bearing and pitch.booleanfalse
showLocateShows a button that flies to the user's current location.booleanfalse
showFullscreenShows a button that toggles fullscreen.booleanfalse
onLocateCalled with the resolved coordinates after a successful locate.(coords: { longitude: number; latitude: number }) => void—
classNameClass names applied to the control cluster.string—

Map.Route

A plain polyline between coordinates.

PropDescriptionTypeDefault
coordinatesLine waypoints, in order. Needs at least 2 points.LngLatTuple[]—
colorLine color.stringtheme --nui-primary
widthLine width, in pixels.number3
opacityLine opacity.number1
dashArrayDash pattern as [dash, gap].[number, number]—
interactiveAttaches onClick / onMouseEnter / onMouseLeave.booleanfalse
onClick / onMouseEnter / onMouseLeaveFired when interactive is true.() => void—
beforeIdInsert this layer before an existing layer id.string—

Map.Arc

Curved lines between point pairs, for flight-path / network-style visualizations.

PropDescriptionTypeDefault
dataArc endpoints.MapArcDatum[]—
curvatureHow much the arc bows away from a straight line.number0.2
samplesPoints used to draw the curve — higher is smoother.number64
paintMapLibre line paint override.LinePainttheme --nui-primary
layoutMapLibre line layout override.LineLayout—
hoverPaintPaint applied to an arc while hovered (interactive only).LinePaint—
interactiveAttaches hover state and onClick / onHover.booleanfalse
onClick / onHoverFired when interactive is true.(event: MapArcEvent | null) => void—
beforeIdInsert this layer before an existing layer id.string—

Map.ClusterLayer

Groups nearby GeoJSON points into clusters that expand as you zoom in.

PropDescriptionTypeDefault
dataPoint features to cluster, or a URL to load them from.string | GeoJSON.FeatureCollection<GeoJSON.Point>—
clusterMaxZoomZoom level above which points no longer cluster.number14
clusterRadiusCluster grouping radius, in pixels.number50
clusterPaintMapLibre paint override for cluster circles.CirclePainttheme --nui-primary
clusterCountPaintMapLibre paint override for the cluster count label.SymbolPaint—
pointPaintMapLibre paint override for individual (non-clustered) points.CirclePainttheme --nui-primary
onClusterClickFired on cluster click. Also auto-zooms to expand the cluster.(event: { clusterId: number; coordinates: LngLatTuple; originalEvent }) => void—
onPointClickFired on an individual point click.(event: { feature; coordinates: LngLatTuple; originalEvent }) => void—
beforeIdInsert these layers before an existing layer id.string—

useMap

Returns the shared map context. Must be called within Map.

function useMap(): {
  map: maplibregl.Map | null;
  isLoaded: boolean;
  isStyleLoaded: boolean;
}

Types

type MapViewport = {
  center: [longitude: number, latitude: number];
  zoom: number;
  bearing: number;
  pitch: number;
}
 
type MapStyleOption = string | maplibregl.StyleSpecification
 
type LngLatTuple = [longitude: number, latitude: number]
 
type MapArcDatum = {
  id: string | number;
  from: LngLatTuple;
  to: LngLatTuple;
}
 
type MapArcEvent<T = MapArcDatum> = {
  arc: T;
  longitude: number;
  latitude: number;
  originalEvent: maplibregl.MapMouseEvent;
}

LinePaint, LineLayout, CirclePaint, SymbolPaint, and SymbolLayout are MapLibre's own style-spec paint/layout types, re-exported as-is — see MapLibre's style spec rather than a NateUI-defined shape.