Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mantine-map

Interactive maps for Mantine, powered by MapLibre GL JS. Markers with Mantine tooltips and popovers, custom Mantine-styled controls (zoom, compass, fullscreen, geolocate), and polygons, all built on Mantine's polymorphic factory and styles API.

Installation

yarn add mantine-map maplibre-gl
# or
npm install mantine-map maplibre-gl

Import the styles once in your app, after the Mantine core styles. mantine-map/styles.css already includes the required maplibre-gl styles, so you do not need to import them separately:

import "@mantine/core/styles.css";
import "mantine-map/styles.css";

mantine-map does not ship any map tiles. Pass a style URL from a tile provider (for example MapTiler or CARTO) via the mapStyle prop. When omitted, the MapLibre demo basemap is used, which is for demonstration only.

mantine-map is published as ES modules only, matching maplibre-gl v6. Bundlers such as Next.js, Vite and webpack 5 need no configuration, and require() works on Node 22.12+ through its built-in ESM support. MapLibre GL JS v6 also requires WebGL2, which is available in all current browsers.

Worker setup (required)

MapLibre GL JS v6 loads its renderer worker from a URL instead of through the bundler's module graph, so the URL has to be supplied once before the first map is created. Without it the map mounts but never draws any tiles, leaving an empty box. setWorkerUrl is re-exported for convenience:

// Vite. `?worker&url` is required, not plain `?url`: the worker imports a sibling chunk at runtime.
import { setWorkerUrl } from "mantine-map";
import workerUrl from "maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url";

setWorkerUrl(workerUrl);
// webpack 5, rspack, rsbuild
import { setWorkerUrl } from "mantine-map";

setWorkerUrl(new URL("maplibre-gl/dist/maplibre-gl-worker.mjs", import.meta.url).toString());

With Next.js, copy both maplibre-gl-worker.mjs and maplibre-gl-shared.mjs out of node_modules/maplibre-gl/dist into public/, then point setWorkerUrl at them there, prefixed with your basePath if the app is deployed under one. The two files must stay side by side, because the worker imports the shared chunk as a sibling and a plain new URL(...) emits only the entry file.

Turbopack can also bundle the worker properly through new Worker(new URL(...)), which resolves that sibling import and needs no copied files. Reaching it is awkward, though: maplibre accepts only a URL string, and Turbopack does not expose the URL of a worker entry the way Vite's ?worker&url does. This repository's documentation site takes that route in docs/maplibre-worker-url.ts, which spells out what it depends on. Prefer the public/ copy above unless you specifically want to avoid the copy step.

Usage

import { Tooltip } from "@mantine/core";
import {
  IconCurrentLocation,
  IconMaximize,
  IconMinimize,
  IconMinus,
  IconNavigation,
  IconPlus,
} from "@tabler/icons-react";
import { Map } from "mantine-map";

function Demo() {
  return (
    <Map
      mapStyle="https://your-tile-provider/style.json"
      initialViewState={{ longitude: 2.3522, latitude: 48.8566, zoom: 11 }}
      style={{ height: 460 }}
    >
      <Map.Controls position="top-right">
        {/* Controls ship no icons, pass your own as children */}
        <Map.ControlGroup>
          <Map.ZoomInControl>
            <IconPlus size={18} />
          </Map.ZoomInControl>
          <Map.ZoomOutControl>
            <IconMinus size={18} />
          </Map.ZoomOutControl>
        </Map.ControlGroup>
        <Map.CompassControl>
          <IconNavigation size={18} />
        </Map.CompassControl>
        <Map.FullscreenControl>
          {(isFullscreen) =>
            isFullscreen ? <IconMinimize size={18} /> : <IconMaximize size={18} />
          }
        </Map.FullscreenControl>
        <Map.GeolocateControl>
          <IconCurrentLocation size={18} />
        </Map.GeolocateControl>
      </Map.Controls>

      <Tooltip label="Paris">
        <Map.Marker longitude={2.3522} latitude={48.8566} />
      </Tooltip>

      <Map.Polygon
        id="zone"
        coordinates={[
          [2.32, 48.87],
          [2.38, 48.87],
          [2.38, 48.84],
          [2.32, 48.84],
        ]}
        fillColor="blue"
      />
    </Map>
  );
}

Every subcomponent is also exported as a flat component (MapMarker, MapControls, MapZoomInControl, MapPolygon, ...) in addition to the Map.* static members.

Components

  • Map — the root. Owns the MapLibre instance and shares it through context. Accepts mapStyle (URL, style object, or a theme-aware { light, dark } pair swapped with the Mantine color scheme), initialViewState, minZoom/maxZoom, interactive, and onMapClick/onMove/onMoveEnd/onMapLoad. onMapClick receives the { longitude, latitude } under the pointer, so it can be handed straight to a Map.Marker to add markers on click, and stays distinct from the root element's plain onClick.
  • Map.Marker — renders custom content (or a default themed pin) at a coordinate. Supports draggable and onDragEnd. Attach a tooltip or popover by wrapping the marker with Mantine's Tooltip or Popover declaratively.
  • Map.Controls + Map.ZoomInControl, Map.ZoomOutControl, Map.CompassControl, Map.FullscreenControl, Map.GeolocateControl — Mantine ActionIcon controls, positioned in any corner. The library ships no icons: pass the icon of your choice as children of each control. Wrap adjacent controls in Map.ControlGroup to join them into one segmented block.
  • Map.Polygon — highlights an area via a GeoJSON fill + outline. Colors accept Mantine color keys.

Local development

  • npm run storybook — start Storybook
  • npm run dev — start the documentation site
  • npm run docgen — regenerate props documentation
  • npm run build — build the package
  • npm test — run the full check (format, typecheck, lint, jest)

Publishing

  1. Login with your npm account (npm login).
  2. Run npm run release:patch, npm run release:minor or npm run release:major to publish a new version.

The documentation is deployed to GitHub Pages automatically on release, based on the repository field in package/package.json. To publish it manually, run npm run docs:deploy.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages