From a845ab075d351e2294a4dd2ec36a864db36b61f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kuna?= <1282324+codecalm@users.noreply.github.com> Date: Mon, 19 Oct 2026 18:49:59 +0200 Subject: [PATCH] Add MapLibre maps: the MapView component, markers, styles, demos and blocks (#3268) --- .agents/skills/astro-scripts/SKILL.md | 1 + .agents/skills/core-js/SKILL.md | 7 +- .build/generate-sri.ts | 19 +- .build/vite.config.helper.mts | 10 +- .changeset/map-blocks.md | 6 + .changeset/map-examples.md | 5 + .changeset/map-markers.md | 5 + .changeset/map-view-component.md | 6 + .changeset/map-view-options.md | 5 + .changeset/maps-maplibre-styles.md | 5 + .changeset/maps-maplibre.md | 7 + core/.build/generate-sri.ts | 4 + core/.build/vite.config.mts | 6 +- core/js/src/global.d.ts | 5 +- core/js/src/map.ts | 645 ++++++++++++++++++ core/js/tabler-map.ts | 6 + core/js/tests/unit/map.spec.ts | 637 +++++++++++++++++ core/libs.json | 6 + core/package.json | 31 +- core/scss/_variables.scss | 24 + core/scss/tabler-vendors.scss | 1 + .../css-var-prefix.test.mjs.snap | 45 ++ core/scss/vendor/_maplibre.scss | 290 ++++++++ core/tsconfig.types.json | 2 +- docs/components/Example.astro | 6 +- docs/content/ui/components/map.mdx | 437 ++++++++++-- docs/layouts/DocsLayout.astro | 8 +- docs/lib/cdn-snippets.ts | 3 + pnpm-lock.yaml | 166 +++++ preview/.env.example | 7 - preview/pages/map-blocks.astro | 39 ++ preview/pages/map-fullsize.astro | 23 +- preview/pages/maps.astro | 372 +++++++++- screenshots/layouts/ScreenshotAppLayout.astro | 28 +- screenshots/layouts/ScreenshotLayout.astro | 28 +- screenshots/pages/map-delivery-tracker.astro | 11 + screenshots/pages/map-live-users.astro | 10 + screenshots/pages/map-store-locator.astro | 10 + .../components/cards/MapAddressPicker.astro | 66 ++ .../components/cards/MapDeliveryTracker.astro | 63 ++ shared/components/cards/MapLiveUsers.astro | 89 +++ shared/components/cards/MapProperties.astro | 92 +++ shared/components/cards/MapServerStatus.astro | 62 ++ shared/components/cards/MapStoreLocator.astro | 110 +++ .../components/cards/MapUsersByCountry.astro | 65 ++ shared/components/demo/Map.astro | 116 ++-- shared/components/demo/MapVector.astro | 2 +- shared/data/maps.json | 14 +- shared/data/menu.json | 5 + shared/data/open-source.json | 7 + shared/layouts/BaseLayout.astro | 18 +- shared/static/maps/berlin-places.geojson | 24 + turbo.json | 2 +- 53 files changed, 3463 insertions(+), 198 deletions(-) create mode 100644 .changeset/map-blocks.md create mode 100644 .changeset/map-examples.md create mode 100644 .changeset/map-markers.md create mode 100644 .changeset/map-view-component.md create mode 100644 .changeset/map-view-options.md create mode 100644 .changeset/maps-maplibre-styles.md create mode 100644 .changeset/maps-maplibre.md create mode 100644 core/js/src/map.ts create mode 100644 core/js/tabler-map.ts create mode 100644 core/js/tests/unit/map.spec.ts create mode 100644 core/scss/vendor/_maplibre.scss delete mode 100644 preview/.env.example create mode 100644 preview/pages/map-blocks.astro create mode 100644 screenshots/pages/map-delivery-tracker.astro create mode 100644 screenshots/pages/map-live-users.astro create mode 100644 screenshots/pages/map-store-locator.astro create mode 100644 shared/components/cards/MapAddressPicker.astro create mode 100644 shared/components/cards/MapDeliveryTracker.astro create mode 100644 shared/components/cards/MapLiveUsers.astro create mode 100644 shared/components/cards/MapProperties.astro create mode 100644 shared/components/cards/MapServerStatus.astro create mode 100644 shared/components/cards/MapStoreLocator.astro create mode 100644 shared/components/cards/MapUsersByCountry.astro create mode 100644 shared/static/maps/berlin-places.geojson diff --git a/.agents/skills/astro-scripts/SKILL.md b/.agents/skills/astro-scripts/SKILL.md index 64a2cbe00..8dd800c96 100644 --- a/.agents/skills/astro-scripts/SKILL.md +++ b/.agents/skills/astro-scripts/SKILL.md @@ -66,6 +66,7 @@ const selector = `#wysiwyg-${id}` - `BEGIN … / END …` comments mark the block in the copied HTML. Use the component name in caps. - A named `init…` function plus the `readyState` guard, never a bare call: the script may be parsed after `DOMContentLoaded` has already fired. +- No `await` (and no `async` function) inside a captured ``} + code={` +${cdnJsTag()} +${cdnMapJsTag()}`} /> -Then create a free account on [mapbox.com](https://www.mapbox.com/) and copy your public access token. It starts with `pk.`. Set it once, before you create a map: +The add-on loads MapLibre GL JS by itself, from `dist/libs/maplibre-gl` next to the Tabler scripts. Tabler uses version 6, which is published as an ES module. When your files are somewhere else, point the `library` option at the module: `data-bs-library="/vendor/maplibre-gl.mjs"`. The library loads two more files from its own folder, `maplibre-gl-shared.mjs` and `maplibre-gl-worker.mjs`, so keep the three together. -```js -mapboxgl.accessToken = 'pk.your-token-here' +If the page sets `window.maplibregl` before the add-on runs, the component uses that and loads nothing. This is the way to go with a bundler: + +```bash +npm install maplibre-gl ``` - - A secret token (`sk.`) must never be sent to the browser. Limit the token to your own domains in the Mapbox dashboard. +```js +import * as maplibregl from 'maplibre-gl' +import 'maplibre-gl/dist/maplibre-gl.css' + +window.maplibregl = maplibregl + +const { MapView } = await import('@tabler/core/dist/js/tabler-map.esm.js') +``` + + + Older versions, including all of version 5, have a known security issue in the code that cleans the attribution text. +Browsers do not load ES modules from a page opened straight from the disk. Use a local server to see the maps while you work. + +Tabler styles the map controls, popups and attribution to match the interface, in light and dark mode. These styles are in `tabler-vendors.css`, so load it after the MapLibre stylesheet: + + + ## Usage -### Markup +### Basic map -Put the map container inside a `ratio` element, so the map keeps its shape on every screen size. Give the inner element an `id` and the `w-100 h-100` classes. +Put the map element inside a `ratio` element, so the map keeps its shape on every screen size. `data-bs-center` takes the longitude first and the latitude second. This is the opposite of what most map services show. - -
-
-
+ + Change the shape with the ratio classes, for example `ratio-21x9` for a wide map or `ratio-1x1` for a square one. -### Init the map +### Map styles -Create the map after the DOM is ready. Pass the id of your container, a style, a zoom level, and a center point. +The map uses a light gray style in light mode and a dark one in dark mode. Tabler softens their colors, so markers and data stand out. Set another style with `data-bs-map-style`: the name of an OpenFreeMap style, or the URL of any MapLibre style. + +| Style | Result | +| --- | --- | +| `positron` | Light gray map. The default in light mode. | +| `dark` | Dark gray map. The default in dark mode. | +| `liberty` | Street map in color. | +| `bright` | Street map with stronger colors. | +| `fiord` | Dark blue map. | + + + + + +`data-bs-map-style-dark` sets the style for dark mode. Styles from other providers work the same way, as long as they follow the MapLibre style format. Check the terms of each provider, as many of them need an API key or a paid plan. + +### Dark mode + +The map follows the nearest `data-bs-theme` and changes its style when the theme changes. Markers and popups stay on the map. To keep one look in both modes, set `data-bs-map-theme` to `light` or `dark`. + +### Markers + +Each child element with `data-bs-lng` and `data-bs-lat` becomes a marker. Use the `.map-marker` class to draw it: a circle in the primary color that can hold an icon, a short count or an avatar. Put a `.map-marker-label` element inside the marker for a short text under it. + +Add `.map-marker-dot` for a small dot, or `.map-marker-pin` for a pin that points down. A pin needs `data-bs-anchor="bottom"`, so its tip sits on the place. Change the color with `.map-marker-{color}`. + + + + + + Store + 12 + + + + + + +Add `data-bs-draggable="true"` to let people move a marker, for example to pick an address. Add `.map-marker-pulse` for a ring that grows out of the marker, for a live position or a place that needs attention. + +HTML markers work well for up to a few hundred places. For more, use [clusters](#clusters). + +### Popups + +Add `data-bs-popup` to a marker for a short text that opens when the marker is clicked. Tabler draws the popup as a small bordered panel with no arrow, and fades it in. + + + + + +For richer content, put a `