Map
A route-and-fleet tracking map — Leaflet under a Flab skin. A slippy map genuinely needs an engine for tiled basemaps, projection and pan/zoom, so Map lazy-loads Leaflet in an effect (it never runs on the server) and disposes it on unmount. The chrome, though, is Flab's: markers are token-styled pins with a pulsing dot for a live vehicle, routes are polylines drawn in resolved token colours, and the zoom / recenter / layers cluster matches the rest of the library. Basemap tiles come from Esri's open light/dark gray-canvas styles (no API key), so the map reads as light or dark alongside the page — pass the resolved theme from useTheme. Because a canvas is opaque to assistive tech, every marker is also a button in a visually-hidden list, giving keyboard users the same reach as a click. The live version is on the Live Tracking showcase.
const route = { id: 'trip', tone: 'info', emphasis: true, points: [ [31.2304, 121.4737], [31.2712, 121.0], [31.2905, 120.8], [31.2989, 120.5853], ],};
const markers = [ { id: 'warehouse', position: [31.2304, 121.4737], kind: 'origin', tone: 'success', label: 'Shanghai Depot', sublabel: '2.4 km' }, { id: 'trk-024', position: [31.2712, 121.0], kind: 'vehicle', label: 'TRK-024', sublabel: '65 km/h' }, { id: 'destination', position: [31.2989, 120.5853], kind: 'destination', label: 'Suzhou Hub', sublabel: '12.8 km' },];
const [selectedId, setSelectedId] = useState('trk-024');
// Import the Leaflet base CSS once in your app: 'leaflet/dist/leaflet.css'.<Map theme={resolvedTheme} center={[31.2712, 121.0]} zoom={10} markers={markers} routes={[route]} selectedId={selectedId} onMarkerSelect={setSelectedId} ariaLabel="Delivery route from the Shanghai depot to the Suzhou hub" height={360} className="rounded-xl border border-hairline"/>Setup
Leaflet ships a base stylesheet that positions the map panes, tiles and zoom animation. Map relies on it but does not import global CSS itself, so import it once in your app — for example in your root stylesheet:
@import 'leaflet/dist/leaflet.css';Props
| Prop | Type | Default | Notes |
|---|---|---|---|
center | MapLatLng | — | Initial [lat, lng]; superseded by fitOnMount when there is content. |
zoom | number | 12 | Initial zoom level. |
minZoom | number | 3 | Lower zoom bound. |
maxZoom | number | 19 | Upper zoom bound. |
theme | 'light' | 'dark' | 'light' | Selects the light/dark basemap. Pass the resolved theme from useTheme. |
markers | MapMarker[] | [] | Pins drawn on the map. |
routes | MapRoute[] | [] | Polylines drawn beneath the markers. |
selectedId | string | null | — | Controlled selection; sets the enlarged pin. Omit for per-marker selected. |
onMarkerSelect | (id: string | null) => void | — | Fires on pin click or the sr-only marker button. |
controls | boolean | true | Show the recenter / zoom / layers cluster. |
interactive | boolean | true | Allow pan and zoom; false renders a static frame. |
fitOnMount | boolean | true | Frame all markers and routes once, on mount. |
attribution | boolean | true | Show the tile attribution (required by most tile terms). |
ariaLabel | string | — | Accessible name describing what the map shows. Required. |
height | number | string | 360 | Map height; the container fills its width. |
MapMarker
| Prop | Type | Default | Notes |
|---|---|---|---|
id | string | — | Stable marker id, reported on selection. |
position | MapLatLng | — | [lat, lng] of the pin. |
kind | 'origin' | 'destination' | 'vehicle' | 'stop' | 'point' | 'point' | Sets the default tone and the pin vs. live-dot treatment. |
label | string | — | Chip shown above the pin. |
sublabel | string | — | Quiet second line in the chip. |
tone | BadgeTone | — | Overrides the tone implied by kind. |
selected | boolean | false | Enlarges the pin and adds a ring (uncontrolled). |
pulse | boolean | — | Adds the pulsing ring; on by default for vehicle. |
MapRoute
| Prop | Type | Default | Notes |
|---|---|---|---|
points | MapLatLng[] | — | Ordered [lat, lng] points. |
tone | BadgeTone | 'info' | Colours the polyline from the token palette. |
variant | 'solid' | 'dashed' | 'solid' | Dashed reads as a planned or secondary segment. |
emphasis | boolean | false | Draws the line heavier, for the primary route. |
id | string | — | Stable key for the route. |
MapLegend
| Prop | Type | Default | Notes |
|---|---|---|---|
items | MapLegendItem[] | — | Each names a dot (tone) or a line sample (line) in text. |