mapcn-react-native
Location

Location puck

The location puck shown on the map. Capability-gated props are documented, not faked.

Renderer support: MapLibre ✓ (⚠ pulsing/scale/images are Mapbox-only)  ·  Mapbox ✓ (⚠ onPress/custom children are MapLibre-only)

npx mapcn-rn add location-puck
import { MapLocationPuck, MAP_LOCATION_PUCK_CAPABILITIES } from "@/components/ui/mapcn";

Overview

MapLocationPuck is one of the four renderer-specific files. MapLibre renders its own JS <UserLocation> component (which can host custom children and an onPress handler); Mapbox renders its native <LocationPuck> (which supports pulsing, a custom scale, and custom top/bearing/shadow images). Neither renderer's feature set is faked on the other -- unsupported props are accepted (so the prop type stays uniform) but produce a __DEV__ console warning and have no effect, and MAP_LOCATION_PUCK_CAPABILITIES (a per-renderer RendererCapabilities object) lets you branch on what's actually supported at runtime.

follow is implemented as camera recentering on every location update (via useMap().flyTo) rather than wiring into Camera's native trackUserLocation/followUserLocation prop, which is declarative and owned by Map's own <Camera> element and not reachable from a sibling component. This is a documented simplification: visually equivalent to native follow for "keep the puck centered," at the cost of one extra location subscription while follow is active.

Props

PropTypeDefaultDescription
visiblebooleantrue
bearing"none" | "heading" | "course""none"Bearing source for the puck's directional indicator.
accuracyRingbooleantrueShows an accuracy ring around the puck.
minDisplacementnumberMeters between position updates.
followfalse | "position" | "heading" | "course"falseRecenters the camera on every location update while set.
onFollowChange(follow) => voidFires whenever the camera is recentered due to follow.
requestPermissionbooleantrueRequests foreground location permission on mount.
onPermissionDenied() => void
pulsingboolean | { color?, radius?: number | "accuracy" }Mapbox only.
scalenumberMapbox only.
images{ top?, bearing?, shadow? }Mapbox only. Custom puck images.
onPress() => voidMapLibre only.
childrenReactNodeMapLibre only. Fully custom JS-rendered puck.
classNamestring

Example

import { Map } from "@/components/ui/mapcn";
import { MapLocationPuck } from "@/components/ui/mapcn";

export function LiveLocation() {
  return (
    <Map defaultViewport={{ center: [-122.4194, 37.7749], zoom: 14 }} className="flex-1">
      <MapLocationPuck bearing="heading" follow="position" pulsing={{ color: "#4285F4" }} />
    </Map>
  );
}

Renderer support

interface RendererCapabilities {
  clusterMinPoints: boolean;
  locationPuckPulsing: boolean;   // Mapbox: true, MapLibre: false
  locationPuckScale: boolean;     // Mapbox: true, MapLibre: false
  locationPuckImages: boolean;    // Mapbox: true, MapLibre: false
  locationPuckPress: boolean;     // Mapbox: false, MapLibre: true
  locationPuckCustomChildren: boolean; // Mapbox: false, MapLibre: true
}

Location tracking · Permissions · Controls

On this page