PaulLeCam / react-leaflet

React components for Leaflet maps
https://react-leaflet.js.org
Other
5.18k stars 887 forks source link

[Question] Change z-index and styles of tooltip of React-Leaflet onMouseover #1102

Open Maria0701 opened 1 year ago

Maria0701 commented 1 year ago

Bug report in v4

I am using react-leaflet with a number of overlapping tooltips. Tooltips should change size on mouseover the tooltip. The behavior should be similar to this https://travel.yandex.ru/hotels/search/?adults=2&bbox=37.41292205549375%2C55.63307944757846~37.796483919901604%2C55.85110332344529&checkinDate=2023-11-21&checkoutDate=2023-11-22&childrenAges=&geoId=213&lastSearchTimeMarker=1697537727502&navigationToken=0&oneNightChecked=false&searchPagePollingId=517ca65a3d0a582bae08c4c3f025a762-1-newsearch&selectedSortId=relevant-first or the one you can see on booking.com

I tried to link the position of tooltip to class, as in the post Dynamically changing z-index for react-leaflet Tooltip, but can not find the correct condition.

Here is my code

// Map code
import "leaflet/dist/leaflet.css";
import { IHotelResult } from "shared/types/IHotel";
import { LeafletMap } from "./leafletMap";
import { LocationMarker } from "./LocationMarker";
import { MapPopupContent } from "./mapPopupContent";
import { useSearchParams } from "react-router-dom";
import { useRef, useEffect } from "react";
import { Popup, Tooltip } from "react-leaflet";

export const MapBlock = ({
  hotels,
  idToOpen
}: {
  hotels: IHotelResult[], 
  idToOpen?: number
}) => {
  const mapRef = useRef<any>(null);
  const markerRef = useRef<any>(null);
  const [URLSearchParams] = useSearchParams();
  const long = Number(URLSearchParams.get('long'));
  const lat = Number(URLSearchParams.get('lat'));
// Show popup on hover on the left-side elements
  useEffect(() => {
    const map = mapRef.current;
    if (!map)  return;

    if (idToOpen !== undefined && markerRef.current) {
      markerRef.current.openPopup();
    }
  },[idToOpen]);

  return (
    <LeafletMap
      center={[lat, long]} 
      zoom={13} 
      scrollWheelZoom={true}
      ref={mapRef}
   >
      {hotels.length > 0 
        ? 
        <>
          {
            hotels.map((item, id) => {
              return (<LocationMarker
              initialCoords={[item.hotel.latitude, item.hotel.longitude]} 
              key={item.id}
              ref={id === idToOpen ? markerRef : null}
              price={item.price}
            >
              <>
                <MapPopupContent
                  img={item.hotel.hotel_information.photo}
                  name={item.hotel.name}
                  price={item.price}
                  stars={item.hotel.stars}
                />
              </>
            </LocationMarker>)})
          }
        </>
        : <></>
      }
    </LeafletMap>
  )
}
// marker code
import { LatLngExpression } from 'leaflet';
import { useState, ReactElement, forwardRef} from 'react';
import { useMapEvents, Marker, Popup, Tooltip } from 'react-leaflet';
import L from "leaflet";

interface ILocationMaker{
  initialCoords?: LatLngExpression | null;
  children: ReactElement;
  price: number;
};

export const LocationMarker = forwardRef(({
  initialCoords = null,
  children, 
  price,
}: ILocationMaker, ref: any) => {
  const [position, setPosition] = useState<LatLngExpression | null>(initialCoords);
  const map = useMapEvents ({
    click() {
      map.locate()
    },
    locationfound(e) {
      setPosition(e.latlng)
      map.flyTo(e.latlng, map.getZoom())
    },
  });

  const customIcon = new L.Icon({
    iconUrl: '/assets/img/location.svg',
    iconSize: [20, 20],
    iconAnchor: [10, 20]
  });

  return position === null 
  ? null 
  : (
      <Marker 
        position={position} 
        icon={customIcon} 
        ref={ref}
        eventHandlers={{
          mouseover: (evt) => console.log(evt.target), 
        }}
      >
        <Tooltip 
          direction="top" 
          opacity={1} 
          permanent
        >
          {`from ${price.toLocaleString()} $`}
        </Tooltip>
        <Popup>
          {children}
        </Popup>
      </Marker>
    )
});