feat(project-overview): hover location card to highlight its map pin
Reverse direction of the existing pin→card flash on the project overview map. Hovering a location card now enlarges + reddens the matching pin on the map and opens its tooltip. Mouse-out reverts. Why hover instead of click: clicking the card title navigates to the location detail page, so any flash effect would never be visible. Hover is the right interaction here. Event delegation on document means cards that appear after htmx swaps (e.g. after a reorder, remove/restore, or assign-modal close) still get the behavior without rewiring. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -161,7 +161,9 @@
|
|||||||
maxZoom: 18,
|
maxZoom: 18,
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
const markers = [];
|
// Marker store keyed by location id so card-click can find + flash
|
||||||
|
// the matching pin (bidirectional highlight).
|
||||||
|
const markersById = {};
|
||||||
const bounds = [];
|
const bounds = [];
|
||||||
withCoords.forEach(loc => {
|
withCoords.forEach(loc => {
|
||||||
const marker = L.circleMarker(loc.latlon, {
|
const marker = L.circleMarker(loc.latlon, {
|
||||||
@@ -174,10 +176,53 @@
|
|||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
marker.bindTooltip(loc.name, { direction: 'top', offset: [0, -6] });
|
marker.bindTooltip(loc.name, { direction: 'top', offset: [0, -6] });
|
||||||
marker.on('click', () => _flashLocationCard(loc.id));
|
marker.on('click', () => _flashLocationCard(loc.id));
|
||||||
markers.push(marker);
|
markersById[loc.id] = marker;
|
||||||
bounds.push(loc.latlon);
|
bounds.push(loc.latlon);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wire up the reverse direction: hovering a card highlights its
|
||||||
|
// pin on the map. Hover-based instead of click-based because
|
||||||
|
// clicking the card navigates to the location detail page, so the
|
||||||
|
// flash would never be visible. Event delegation so cards that
|
||||||
|
// appear later (htmx swap or reorder) still work.
|
||||||
|
let _hoverPinId = null;
|
||||||
|
document.addEventListener('mouseover', (e) => {
|
||||||
|
const card = e.target.closest('.location-card');
|
||||||
|
if (!card) return;
|
||||||
|
const locId = card.dataset.locationId;
|
||||||
|
if (locId === _hoverPinId) return;
|
||||||
|
if (_hoverPinId) _unhighlightPin(_hoverPinId);
|
||||||
|
_highlightPin(locId);
|
||||||
|
_hoverPinId = locId;
|
||||||
|
});
|
||||||
|
document.addEventListener('mouseout', (e) => {
|
||||||
|
const card = e.target.closest('.location-card');
|
||||||
|
if (!card) return;
|
||||||
|
// Only un-highlight if the mouse actually left the card,
|
||||||
|
// not just moved to a child element.
|
||||||
|
const related = e.relatedTarget && e.relatedTarget.closest('.location-card');
|
||||||
|
if (related === card) return;
|
||||||
|
if (_hoverPinId) {
|
||||||
|
_unhighlightPin(_hoverPinId);
|
||||||
|
_hoverPinId = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function _highlightPin(locId) {
|
||||||
|
const marker = markersById[locId];
|
||||||
|
if (!marker) return;
|
||||||
|
marker.setStyle({ radius: 12, fillColor: '#dc2626', weight: 3 });
|
||||||
|
marker.openTooltip();
|
||||||
|
marker.bringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _unhighlightPin(locId) {
|
||||||
|
const marker = markersById[locId];
|
||||||
|
if (!marker) return;
|
||||||
|
marker.setStyle({ radius: 8, fillColor: '#f48b1c', weight: 2 });
|
||||||
|
marker.closeTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
if (bounds.length === 1) {
|
if (bounds.length === 1) {
|
||||||
map.setView(bounds[0], 14);
|
map.setView(bounds[0], 14);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user