Content & marketing
Map Marker List code
Copy the implementation or inspect every file that belongs to this component unit.
resources/views/components/ui/map-marker-list.blade.php
@props([
'markers' => [],
'paths' => [],
'allowPlacement' => false,
'placementLabel' => 'Waypoint',
])
@php
$markerItems = collect($markers)->values();
$pathItems = collect($paths)->values();
$sequentialPath = $pathItems->contains(fn (array $path): bool => (bool) ($path['sequential'] ?? false));
$markerVariant = function (array $marker): string {
$explicit = strtolower((string) ($marker['variant'] ?? ''));
if (in_array($explicit, ['brand', 'red', 'amber', 'green', 'blue', 'gray'], true)) {
return $explicit;
}
return match (strtolower((string) ($marker['type'] ?? ''))) {
'city' => 'brand',
'town', 'village' => 'amber',
'military', 'danger' => 'red',
'supply', 'medical' => 'green',
'objective', 'waypoint' => 'blue',
'neutral' => 'gray',
default => 'brand',
};
};
$markerInitial = function (array $marker): string {
$label = trim((string) ($marker['label'] ?? $marker['title'] ?? ''));
return $label !== '' ? strtoupper(substr($label, 0, 1)) : '•';
};
@endphp
<div {{ $attributes }}>
@if ($pathItems->isNotEmpty())
<div class="mb-3 space-y-2 border-b border-gray-200 px-2 pb-3 dark:border-gray-800">
@foreach ($pathItems as $path)
@php
$pathVariant = match (strtolower((string) ($path['variant'] ?? 'brand'))) {
'red' => 'red',
'amber' => 'amber',
'green' => 'green',
'blue' => 'blue',
'gray' => 'gray',
default => 'brand',
};
@endphp
<div class="flex items-center gap-2 rounded-lg bg-gray-50 px-2.5 py-2 dark:bg-gray-950/60">
<span @class([
'h-0.5 w-5 rounded-full',
'bg-brand-600' => $pathVariant === 'brand',
'bg-red-600' => $pathVariant === 'red',
'bg-amber-600' => $pathVariant === 'amber',
'bg-green-600' => $pathVariant === 'green',
'bg-accent-600' => $pathVariant === 'blue',
'bg-gray-600' => $pathVariant === 'gray',
])></span>
<span class="min-w-0 truncate text-xs font-semibold text-gray-700 dark:text-gray-300">
{{ $path['label'] ?? 'Path' }}
</span>
@if ($path['sequential'] ?? false)
<x-ui.badge variant="gray" size="sm">Sequential</x-ui.badge>
@endif
</div>
@endforeach
</div>
@endif
<ul class="space-y-1" data-map-marker-list>
@unless ($allowPlacement)
@foreach ($markerItems as $index => $marker)
@php
$variant = $markerVariant($marker);
$badgeVariant = match ($variant) {
'red' => 'red',
'amber' => 'amber',
'green' => 'green',
'blue' => 'blue',
'gray' => 'gray',
default => 'brand',
};
@endphp
<li>
<button
type="button"
data-map-marker-item
data-map-marker-index="{{ $index }}"
class="harbour-map-marker-list-item group flex w-full items-start gap-3 rounded-xl px-3 py-2.5 text-left transition hover:bg-gray-50 dark:hover:bg-gray-800/60"
>
<span @class([
'inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-xs font-bold ring-1',
'bg-brand-50 text-brand-700 ring-brand-100 dark:bg-brand-950/60 dark:text-brand-300 dark:ring-brand-900/60' => $variant === 'brand',
'bg-red-50 text-red-700 ring-red-100 dark:bg-red-950/60 dark:text-red-300 dark:ring-red-900/60' => $variant === 'red',
'bg-amber-50 text-amber-700 ring-amber-100 dark:bg-amber-950/60 dark:text-amber-300 dark:ring-amber-900/60' => $variant === 'amber',
'bg-green-50 text-green-700 ring-green-100 dark:bg-green-950/60 dark:text-green-300 dark:ring-green-900/60' => $variant === 'green',
'bg-accent-50 text-accent-700 ring-accent-100 dark:bg-accent-950/60 dark:text-accent-300 dark:ring-accent-900/60' => $variant === 'blue',
'bg-gray-100 text-gray-700 ring-gray-200 dark:bg-gray-800 dark:text-gray-300 dark:ring-gray-700' => $variant === 'gray',
])>
{{ $markerInitial($marker) }}
</span>
<span class="min-w-0 flex-1">
<span class="flex items-center gap-2">
@if (isset($marker['order']) || ($sequentialPath && $markerItems->count() > 1))
<span class="inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-gray-100 px-1.5 text-[0.6875rem] font-bold tabular-nums text-gray-600 dark:bg-gray-800 dark:text-gray-300">
{{ $marker['order'] ?? ($index + 1) }}
</span>
@endif
<span class="truncate text-sm font-semibold text-gray-900 dark:text-white">
{{ $marker['label'] ?? $marker['title'] ?? 'Map marker' }}
</span>
</span>
@if (filled($marker['type'] ?? null))
<x-ui.badge :variant="$badgeVariant" size="sm" class="mt-1">{{ $marker['type'] }}</x-ui.badge>
@endif
@if (filled($marker['description'] ?? null))
<span class="mt-1 block line-clamp-2 text-xs leading-5 text-gray-500 dark:text-gray-400">
{{ $marker['description'] }}
</span>
@endif
@if (isset($marker['x'], $marker['z']))
<span class="mt-1 block text-[0.6875rem] font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">
X {{ number_format((float) $marker['x'], 0) }} / Z {{ number_format((float) $marker['z'], 0) }}
</span>
@endif
</span>
<x-ui.icon name="arrow-right" size="sm" class="mt-1 shrink-0 text-gray-300 transition group-hover:text-brand-600 dark:text-gray-600 dark:group-hover:text-brand-400" />
</button>
</li>
@endforeach
@else
<li data-map-marker-empty class="rounded-xl px-3 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
Click the map to place your first {{ Str::lower($placementLabel) }}.
</li>
@endunless
</ul>
</div>