GeoJSON

Docs / GeoJSON

Overview

The <x-map-geojson> component renders any GeoJSON as map layers: polygons become fills with outlines, lines become strokes and points become circles. Use it for delivery zones, boundaries, choropleths, trails or any shapes you already have as GeoJSON.

:data accepts a FeatureCollection, a single Feature or a bare geometry as a PHP array, or a URL string that MapLibre fetches in the browser. Default colors are neutral and follow the map's light/dark theme.

Basic Usage

The smallest example: a single polygon with the default theme-aware styling.

blade
<x-map height="320px">
    <x-map-geojson
        :data="[
            'type' => 'Polygon',
            'coordinates' => [[[-0.15, 51.52], [-0.12, 51.52], [-0.12, 51.50], [-0.15, 51.50], [-0.15, 51.52]]],
        ]"
        :fit-bounds="true"
    />
</x-map>

Overlay on a Map

Style features from their properties with expressions such as ['get', 'color'], highlight the hovered feature with the *-hover-paint props, and describe it in a tooltip slot. Set :interactive="true" to enable hover, tooltips, popups and click events (GeoJSON layers are not interactive by default). Hover the delivery zones and depots:

How layers are built

Each geometry type gets its own layer, and every paint prop is merged over theme-aware defaults:

Paint propApplies toDefaults
:fill-paintPolygon, MultiPolygonfill-color light grey (dark grey in dark mode)
:line-paintLineString, MultiLineString and polygon outlinesline-color white (near-black in dark mode), line-width 0.5
:circle-paintPoint, MultiPointcircle-color grey, circle-radius 5, white 1.5px stroke
Pass false to a paint prop to drop that layer entirely, e.g. :line-paint="false" for fills without outlines. Hover works without promote-id because feature ids are generated automatically; set promote-id when you need a stable id from a property.

Blank Map

Add blank to <x-map> for a transparent style with no basemap, so your GeoJSON is the whole map. This example loads Natural Earth country outlines from a URL and colors them by continent:

When data is a URL, the file is fetched by the browser, so the server must allow cross-origin requests. :fit-bounds only works with inline array data; set :center and :zoom (or the map's :bounds) for URL data.

Livewire Events

Interactive GeoJSON layers dispatch map:geojson-clicked and map:geojson-hovered with the layer id, the feature (id, properties, geometry), the pointer lat/lng and the mapId. When the pointer leaves a feature, map:geojson-hovered fires with feature: null.

php
use Livewire\Attributes\On;

public ?string $selectedZone = null;

#[On('map:geojson-clicked')]
public function selectZone(string $id, ?array $feature = null): void
{
    if ($id === 'delivery-zones') {
        $this->selectedZone = $feature['properties']['name'] ?? null;
    }
}

// Replace the data without re-rendering the component
$this->dispatch('map:update-geojson-delivery-zones', data: $this->zones);

Like every map layer, <x-map-geojson> also reacts to Livewire state: change the bound :data or paint props and the layer updates in place on the next render.

Props

PropTypeDefaultDescription
:dataarray|string[]FeatureCollection, Feature or Geometry array, or a URL to a GeoJSON file
id?stringuuidLayer id, used in event payloads and map:update-geojson-{id}
promote-id?stringnullFeature property to use as the feature id (ids are generated when omitted)
:fill-paintarray|false|nullnullFill paint for polygons, merged over defaults. false drops the layer
:line-paintarray|false|nullnullLine paint for lines and polygon outlines. false drops the layer
:circle-paintarray|false|nullnullCircle paint for points. false drops the layer
:fill-hover-paint?arraynullFill paint applied to the hovered feature
:line-hover-paint?arraynullLine paint applied to the hovered feature
:circle-hover-paint?arraynullCircle paint applied to the hovered feature
:interactiveboolfalseEnable hover, tooltip, popup and click events
before-id?stringnullInsert the layers below this existing layer id
:fit-boundsboolfalseFit the map to the data once loaded (inline data only)
:fit-bounds-paddingint40Padding in pixels for :fit-bounds

Slots

SlotDescription
tooltipHTML shown on hover. {property}, {lat} and {lng} placeholders are filled in (values are HTML-escaped)
popupHTML shown in a popup on click, with the same placeholders