Skip to content
Brok UI

Loading…

No results

Map Blocks

Open source

Interactive MapLibre maps — analytics overview, logistics network, geographic heatmap and live delivery tracking.

Preview

resources/views/blocks/maps-heatmap.blade.php Blade
@props([
    'heading' => 'Seismic activity',
    'subheading' => 'Earthquake density, last 30 days',
    // [longitude, latitude] the globe is initially centred on.
    'center' => [150, 0],
    'zoom' => 1.3,
    // Low → high density colour ramp as TOKEN NAMES (resolved to themed colours
    // at runtime — never raw hex). The map renders the heatmap from these.
    'ramp' => ['info', 'primary', 'warning', 'destructive'],
    // Optional override: a GeoJSON FeatureCollection (PHP array) of Point
    // features, each with a numeric properties.mag weight. Defaults below.
    'quakes' => null,
])

@php
    // Authored (non-random) sample of recent quakes scattered around the Pacific
    // "Ring of Fire": Japan, Indonesia/Philippines, the Andes, Alaska, the US
    // West Coast and New Zealand. Each [lng, lat, mag].
    $points = $quakes ?? [
        // Japan / Kuril arc
        [142.4, 38.3, 6.8], [141.0, 37.1, 4.2], [143.9, 41.6, 5.1], [140.2, 35.7, 3.4],
        [138.5, 34.9, 2.6], [144.7, 43.2, 4.9], [131.6, 33.2, 3.1],
        // Philippines / Indonesia
        [125.4, 7.1, 6.2], [122.8, 0.9, 5.4], [119.7, -3.6, 4.7], [127.3, 1.5, 3.8],
        [112.9, -8.2, 5.9], [106.4, -6.9, 2.9], [130.1, -3.4, 4.1], [124.0, 12.7, 3.6],
        // New Zealand / Tonga
        [174.8, -41.3, 5.7], [176.2, -38.6, 4.4], [-175.2, -20.1, 6.4], [178.0, -37.4, 3.2],
        // Alaska / Aleutians
        [-150.6, 61.2, 6.1], [-153.4, 59.8, 4.6], [-162.3, 54.7, 5.3], [-147.9, 63.1, 2.8],
        // US West Coast
        [-122.3, 37.8, 4.0], [-118.4, 34.1, 3.5], [-124.2, 40.6, 5.0], [-121.9, 36.6, 2.4],
        [-116.9, 33.4, 3.7],
        // Mexico / Central America
        [-99.1, 16.8, 5.6], [-104.7, 19.2, 4.3], [-91.3, 14.1, 3.9],
        // Andes (Peru, Chile)
        [-71.6, -33.0, 6.6], [-70.4, -23.7, 5.2], [-72.9, -38.1, 4.8], [-77.0, -12.0, 3.3],
        [-69.8, -18.5, 5.5], [-73.2, -45.4, 4.1],
        // Caribbean / Cascadia tail
        [-61.0, 14.6, 3.0], [-126.7, 47.5, 4.5], [155.2, -6.3, 6.0], [167.1, -15.4, 4.2],
    ];

    // Build an inline GeoJSON FeatureCollection from the authored list.
    $features = [];
    foreach ($points as [$lng, $lat, $mag]) {
        $features[] = [
            'type' => 'Feature',
            'properties' => ['mag' => $mag],
            'geometry' => ['type' => 'Point', 'coordinates' => [$lng, $lat]],
        ];
    }

    $geojson = ['type' => 'FeatureCollection', 'features' => $features];
    $count = count($features);

    // Legend swatches: token bg classes, low → high density.
    $legend = [
        ['class' => 'bg-info', 'label' => __('Low')],
        ['class' => 'bg-primary', 'label' => __('Moderate')],
        ['class' => 'bg-warning', 'label' => __('High')],
        ['class' => 'bg-destructive', 'label' => __('Severe')],
    ];
@endphp

<x-ui.card {{ $attributes->merge(['class' => 'w-full']) }}>
    <x-ui.card.header>
        <div class="flex flex-wrap items-start justify-between gap-4">
            <div class="space-y-2">
                <x-ui.card.title>{{ __($heading) }}</x-ui.card.title>
                <x-ui.card.description>{{ __($subheading) }}</x-ui.card.description>
            </div>
            <x-ui.badge variant="secondary" class="tabular-nums">
                {{ trans_choice('{1} :count event|[2,*] :count events', $count, ['count' => number_format($count)]) }}
            </x-ui.badge>
        </div>
    </x-ui.card.header>

    <x-ui.card.content class="space-y-4">
        <x-ui.map
            projection="globe"
            :center="$center"
            :zoom="$zoom"
            height="520px"
            :label="__('Earthquake density heatmap')"
            :heatmap="[
                'data' => $geojson,
                'weight' => 'mag',
                'intensity' => 1,
                'radius' => 30,
                'colors' => $ramp,
            ]"
        >
            <x-ui.map.controls position="top-right" show-zoom />
        </x-ui.map>

        <x-ui.separator />

        {{-- Density legend: low → high using token swatch chips. --}}
        <div class="flex flex-wrap items-center gap-x-4 gap-y-2">
            <span class="text-xs font-medium text-muted-foreground">{{ __('Low') }}</span>
            <ul class="flex flex-wrap items-center gap-4">
                @foreach ($legend as $step)
                    <li class="flex items-center gap-2 text-xs text-muted-foreground">
                        <span class="size-3 shrink-0 rounded-full {{ $step['class'] }}" aria-hidden="true"></span>
                        {{ $step['label'] }}
                    </li>
                @endforeach
            </ul>
            <span class="text-xs font-medium text-muted-foreground">{{ __('High') }}</span>
        </div>
    </x-ui.card.content>
</x-ui.card>

Installation

terminal
php artisan ui:add blocks/maps-heatmap

Installs these dependencies automatically:

Registry contract

Install confidence

php artisan ui:add blocks/maps-heatmap writes only the generated targets below. The CLI validates each file hash before writing and prompts before replacing local changes unless --force is used.

Version
1.0.4
License
open
Stability
stable
Contract
v1
Foundation
≥ 1.0.0
Type Generated target
blade resources/views/blocks/maps-heatmap.blade.php

Registry dependencies

card badge separator map

Package dependencies

composer: jml/brok:^0.2

npm: maplibre-gl

Use with AI

A brief for your coding agent: what the block is, the install command, how to render it, its props and the rules. Copy it, or open a prompt about this block in an assistant.

maps-heatmap.md
# Brok UI block: Map Heatmap (`maps-heatmap`)

Geographic density heatmap of seismic activity around the Pacific Ring of Fire.

Brok UI is a Laravel Blade registry. `ui:add` copies this block into the app as plain Blade the app owns; it composes installed `<brok:*>` primitives and semantic design tokens.

## Install

```bash
php artisan ui:add blocks/maps-heatmap
```

## Render it

```blade
<x-blocks.maps-heatmap />
```

## Props

- `heading` (string, default `Seismic activity`) — Card title.
- `subheading` (string, default `Earthquake density, last 30 days`) — Supporting copy under the heading.
- `center` (array, default `[150, 0]`) — [longitude, latitude] the globe is initially centred on.
- `zoom` (float, default `1.3`) — Initial zoom level.
- `ramp` (array, default `['info', 'primary', 'warning', 'destructive']`) — Low-to-high heatmap colour ramp as token names, never raw hex.
- `quakes` (mixed|null, default `null`) — Optional GeoJSON FeatureCollection of Point features with a numeric properties.mag weight; null uses a sample Ring-of-Fire dataset.

## Use when

- Visualising geographic point-density data, such as seismic events, as a heatmap layer on a rotating globe.
- Showing a low-to-high legend alongside an event-count badge instead of discrete markers.

## Avoid when

- Needing discrete hub or courier markers with popups instead of a diffuse density layer; use maps-analytics, maps-logistics, or maps-delivery-tracker.

## Rules

- Render the installed block with `<x-blocks.maps-heatmap />` and pass data through its props; edit the copied file only for structural changes.
- Keep the semantic design tokens (`bg-background`, `text-muted-foreground`); never swap in raw colour utilities.
- Keep the `data-slot` attributes and the logical (start/end) spacing so the markup still mirrors under `dir="rtl"`.

## Links

- Docs: https://brokui.dev/blocks/maps-heatmap
- Registry JSON (files, props, contract): https://brokui.dev/r/open/blocks/maps-heatmap.json

Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.

Guidance

Use when

  • Visualising geographic point-density data, such as seismic events, as a heatmap layer on a rotating globe.
  • Showing a low-to-high legend alongside an event-count badge instead of discrete markers.

Avoid when

  • Needing discrete hub or courier markers with popups instead of a diffuse density layer; use maps-analytics, maps-logistics, or maps-delivery-tracker.

Anti-patterns

  • Do not replace semantic props with conflicting utility classes.
  • Do not remove labels, focus styles, or state attributes.
Anatomy
header with heading and event-count badge globe map with heatmap layer low-to-high density legend

Usage

Render the block as a component, passing data where useful:

resources/views/welcome.blade.php Blade
<x-blocks.maps-heatmap />

Built from primitives

Composes <brok:*> Semantic tokens Re-themeable RTL-ready

This block composes installed <brok:*> primitives and semantic design tokens only — it does not reimplement any primitive. Re-theme it (light, dark, admin, customer) by editing CSS variables; flip the preview to RTL to confirm it mirrors.

Source

The exact, editable file ui:add writes into your app. The preview above renders this same source — there are no preview-only blocks.

resources/views/blocks/maps-heatmap.blade.php Blade
@props([
    'heading' => 'Seismic activity',
    'subheading' => 'Earthquake density, last 30 days',
    // [longitude, latitude] the globe is initially centred on.
    'center' => [150, 0],
    'zoom' => 1.3,
    // Low → high density colour ramp as TOKEN NAMES (resolved to themed colours
    // at runtime — never raw hex). The map renders the heatmap from these.
    'ramp' => ['info', 'primary', 'warning', 'destructive'],
    // Optional override: a GeoJSON FeatureCollection (PHP array) of Point
    // features, each with a numeric properties.mag weight. Defaults below.
    'quakes' => null,
])

@php
    // Authored (non-random) sample of recent quakes scattered around the Pacific
    // "Ring of Fire": Japan, Indonesia/Philippines, the Andes, Alaska, the US
    // West Coast and New Zealand. Each [lng, lat, mag].
    $points = $quakes ?? [
        // Japan / Kuril arc
        [142.4, 38.3, 6.8], [141.0, 37.1, 4.2], [143.9, 41.6, 5.1], [140.2, 35.7, 3.4],
        [138.5, 34.9, 2.6], [144.7, 43.2, 4.9], [131.6, 33.2, 3.1],
        // Philippines / Indonesia
        [125.4, 7.1, 6.2], [122.8, 0.9, 5.4], [119.7, -3.6, 4.7], [127.3, 1.5, 3.8],
        [112.9, -8.2, 5.9], [106.4, -6.9, 2.9], [130.1, -3.4, 4.1], [124.0, 12.7, 3.6],
        // New Zealand / Tonga
        [174.8, -41.3, 5.7], [176.2, -38.6, 4.4], [-175.2, -20.1, 6.4], [178.0, -37.4, 3.2],
        // Alaska / Aleutians
        [-150.6, 61.2, 6.1], [-153.4, 59.8, 4.6], [-162.3, 54.7, 5.3], [-147.9, 63.1, 2.8],
        // US West Coast
        [-122.3, 37.8, 4.0], [-118.4, 34.1, 3.5], [-124.2, 40.6, 5.0], [-121.9, 36.6, 2.4],
        [-116.9, 33.4, 3.7],
        // Mexico / Central America
        [-99.1, 16.8, 5.6], [-104.7, 19.2, 4.3], [-91.3, 14.1, 3.9],
        // Andes (Peru, Chile)
        [-71.6, -33.0, 6.6], [-70.4, -23.7, 5.2], [-72.9, -38.1, 4.8], [-77.0, -12.0, 3.3],
        [-69.8, -18.5, 5.5], [-73.2, -45.4, 4.1],
        // Caribbean / Cascadia tail
        [-61.0, 14.6, 3.0], [-126.7, 47.5, 4.5], [155.2, -6.3, 6.0], [167.1, -15.4, 4.2],
    ];

    // Build an inline GeoJSON FeatureCollection from the authored list.
    $features = [];
    foreach ($points as [$lng, $lat, $mag]) {
        $features[] = [
            'type' => 'Feature',
            'properties' => ['mag' => $mag],
            'geometry' => ['type' => 'Point', 'coordinates' => [$lng, $lat]],
        ];
    }

    $geojson = ['type' => 'FeatureCollection', 'features' => $features];
    $count = count($features);

    // Legend swatches: token bg classes, low → high density.
    $legend = [
        ['class' => 'bg-info', 'label' => __('Low')],
        ['class' => 'bg-primary', 'label' => __('Moderate')],
        ['class' => 'bg-warning', 'label' => __('High')],
        ['class' => 'bg-destructive', 'label' => __('Severe')],
    ];
@endphp

<x-ui.card {{ $attributes->merge(['class' => 'w-full']) }}>
    <x-ui.card.header>
        <div class="flex flex-wrap items-start justify-between gap-4">
            <div class="space-y-2">
                <x-ui.card.title>{{ __($heading) }}</x-ui.card.title>
                <x-ui.card.description>{{ __($subheading) }}</x-ui.card.description>
            </div>
            <x-ui.badge variant="secondary" class="tabular-nums">
                {{ trans_choice('{1} :count event|[2,*] :count events', $count, ['count' => number_format($count)]) }}
            </x-ui.badge>
        </div>
    </x-ui.card.header>

    <x-ui.card.content class="space-y-4">
        <x-ui.map
            projection="globe"
            :center="$center"
            :zoom="$zoom"
            height="520px"
            :label="__('Earthquake density heatmap')"
            :heatmap="[
                'data' => $geojson,
                'weight' => 'mag',
                'intensity' => 1,
                'radius' => 30,
                'colors' => $ramp,
            ]"
        >
            <x-ui.map.controls position="top-right" show-zoom />
        </x-ui.map>

        <x-ui.separator />

        {{-- Density legend: low → high using token swatch chips. --}}
        <div class="flex flex-wrap items-center gap-x-4 gap-y-2">
            <span class="text-xs font-medium text-muted-foreground">{{ __('Low') }}</span>
            <ul class="flex flex-wrap items-center gap-4">
                @foreach ($legend as $step)
                    <li class="flex items-center gap-2 text-xs text-muted-foreground">
                        <span class="size-3 shrink-0 rounded-full {{ $step['class'] }}" aria-hidden="true"></span>
                        {{ $step['label'] }}
                    </li>
                @endforeach
            </ul>
            <span class="text-xs font-medium text-muted-foreground">{{ __('High') }}</span>
        </div>
    </x-ui.card.content>
</x-ui.card>

Ownership & lifecycle

Owner, release state, review evidence and adoption for this item.
Owner
Platform UI (@JoshJML)
Current version
1.0.4
Status
Stable
License
open
Deprecation
Not deprecated
Contract
v1
Foundation
≥ 1.0.0