hover and selected states for markers

This commit is contained in:
2025-07-28 17:47:50 +05:00
parent a1b896b37f
commit 99fa5a93d0
3 changed files with 37 additions and 10 deletions
+4 -2
View File
@@ -34,7 +34,7 @@ export default function GoogleMap({
map.panTo(mapCenter);
map.setZoom(defaultZoom);
}
}, [mobile, mobileActive, map]);
}, [mobile, mobileActive, defaultZoom, mapCenter, map]);
useEffect(() => {
if (!mobileActive) setMapMarkersFilter("All");
@@ -52,7 +52,9 @@ export default function GoogleMap({
defaultZoom={defaultZoom}
disableDefaultUI={true}
minZoom={minZoom}
gestureHandling={!mobile || mobileActive ? "greedy" : "none"}
gestureHandling={
mobile ? (mobileActive ? "greedy" : "none") : "cooperative"
}
>
{markers && (
<GoogleMapMarkers data={markers} filter={mapMarkersFilter} />
@@ -42,6 +42,7 @@ export default function GoogleMapMarkers({
}) {
const map = useMap();
const [markers, setMarkers] = useState<{ [key: string]: Marker }>({});
const [selectedMarker, setSelectedMarker] = useState<number | null>(null);
const clusterer = useRef<MarkerClusterer | null>(null);
useEffect(() => {
@@ -64,6 +65,8 @@ export default function GoogleMapMarkers({
if (!marker && !markers[key]) return;
setMarkers((prev) => {
if (prev[key] === marker) return prev;
if (marker) {
return { ...prev, [key]: marker };
} else {
@@ -84,6 +87,8 @@ export default function GoogleMapMarkers({
markerKey={index}
poi={poi}
setMarkerRef={setMarkerRef}
isSelected={selectedMarker === index}
setSelectedMarker={setSelectedMarker}
>
{poi.customMarker}
</MapMarker>
+28 -8
View File
@@ -1,5 +1,6 @@
import { AdvancedMarker, useMap } from "@vis.gl/react-google-maps";
import type { Marker } from "@googlemaps/markerclusterer";
import { useEffect, useRef, useState } from "react";
import IGMapPoi from "../../types/IGMapPoi";
interface IGMapMarker {
@@ -7,6 +8,8 @@ interface IGMapMarker {
poi: IGMapPoi;
setMarkerRef: (marker: Marker | null, key: string) => void | undefined;
children: React.ReactNode;
isSelected: boolean;
setSelectedMarker: React.Dispatch<React.SetStateAction<number | null>>;
}
export default function MapMarker({
@@ -14,30 +17,47 @@ export default function MapMarker({
children,
markerKey,
setMarkerRef,
isSelected,
setSelectedMarker,
}: IGMapMarker) {
const map = useMap();
const { location, ignoreClusterization, label } = poi;
const [isHovered, setIsHovered] = useState(false);
const markerRef = useRef(null);
useEffect(() => {
if (!ignoreClusterization) {
setMarkerRef(markerRef.current, markerKey.toString());
}
}, [ignoreClusterization, markerKey, setMarkerRef]);
return (
<AdvancedMarker
key={markerKey}
position={location}
ref={(marker) => {
if (!ignoreClusterization) {
setMarkerRef(marker, markerKey.toString());
}
}}
ref={markerRef}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onClick={() => {
map?.panTo(location);
map?.panTo({ lat: location.lat, lng: location.lng + 0.001 }); // 0.001 is a small align to fit long labels (generally for mobile devices)
map?.setZoom(17);
setSelectedMarker(markerKey);
}}
>
<div
className={`relative flex items-center gap-x-2 hover:[&>.label-container]:opacity-100 hover:[&>.label-container]:left-[calc(100%-38px)] hover:[&>.label-container]:pointer-events-auto hover:[&>.label-container]:z-140 hover:[&>.gmap-img-container]:z-150`}
className={`relative flex items-center gap-x-2 ${
isHovered || isSelected ? "[&>.gmap-img-container]:z-150" : ""
}`}
>
{children}
{label && (
<div className="label-container text-black absolute text-s left-0 opacity-0 w-max pointer-events-none transition-[left,opacity] bg-white pl-11 pr-3 py-2.5 rounded-2xl">
<div
className={`label-container text-black absolute text-s left-0 opacity-0 w-max pointer-events-none transition-[left,opacity] bg-white pl-11 pr-3 py-2.5 rounded-2xl ${
isHovered || isSelected
? "opacity-100 left-[calc(100%-38px)] pointer-events-auto z-140"
: ""
}`}
>
{label}
</div>
)}