Google Places Autocomplete container is not fixed to its associated input element

Viewed 208

I have created a reusable component "SearchBar" in my NextJS app that loads Google Autocomplete via script and without a third-party library.

I used this component on my home page to search for the user's desired location. Now I tried to use this component in the header as well, which also works, but I just can't get the container with the search results (pac-container in CSS) to be sticky to the input.

On the homepage this works wonderfully, but if I search for a location in the input of the header and the pac-container appears, it stays in place on the screen and does not remain fixed in position in relation to its input element.

I have already tried all known combinations of Z-index and position like "fixed" etc., but unfortunately I cannot find a solution.

A big part of my CSS is done with Tailwind (https://tailwindcss.com)

Does anyone have any ideas?

let autoComplete;

export const loadScript = (url, callback) => {
  let script = document.createElement("script");
  script.type = "text/javascript";

  if (script.readyState) {
    script.onreadystatechange = function () {
      if (script.readyState === "loaded" || script.readyState === "complete") {
        script.onreadystatechange = null;
        callback();
      }
    };
  } else {
    script.onload = () => callback();
  }

  script.src = url;
  document.getElementsByTagName("head")[0].appendChild(script);
};

export function handleScriptLoad(updateQuery, autoCompleteRef) {
  autoComplete = new window.google.maps.places.Autocomplete(
    autoCompleteRef.current,
    { types: ["(cities)"] }
  );
  autoComplete.setFields(["address_components", "formatted_address"]);
  autoComplete.addListener("place_changed", () =>
    handlePlaceSelect(updateQuery)
  );
}

export async function handlePlaceSelect(updateQuery) {
  const addressObject = autoComplete.getPlace();
  const query = addressObject.formatted_address;
  updateQuery(query);
  console.log(addressObject);
}
html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}

.pac-container {
  position: relative;
  z-index: 0;
  background-color: #fff;
  border-radius: 0px;
  border: 2px solid #060606;
  margin-top: 10px;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  -webkit-box-shadow: none;
  -moz-box-shadow: none;
  box-shadow: none;
}

.pac-item:hover {
  background-color: #eeeeee;
  cursor: pointer;
}
.pac-item-selected,
.pac-item-selected:hover {
  background-color: #ebf2fe;
}

.pac-item {
  height: 50px;
  font-family: Poppins;
  font-size: 13px;
  padding: 5px;
  padding-left: 10px;
  padding-top: 10px;
}

.pac-placeholder {
  color: gray;
}

.pac-container:after {
  background-image: none !important;
  height: 0px;
}

.pac-icon {
  background: url("/icons/locationIcon.svg") no-repeat center;
  background-size: 16px;
  margin: 5px 10px 6px 0;
  vertical-align: middle;
}
import { useState, useEffect, useRef } from "react";
import LocationIcon from "../public/icons/locationIcon.svg";
import { loadScript, handleScriptLoad } from "../services/google";

interface Props {
  query: string;
  setQuery: (event) => void;
}

export const SearchBar = ({ query, setQuery }: Props) => {
  const autoCompleteRef = useRef(null);
  const [isSearchFocused, setIsSearchFocused] = useState(false);

  useEffect(() => {
    loadScript(
      `https://maps.googleapis.com/maps/api/js?key=${process.env.NEXT_PUBLIC_GOOGLE_PLACES_API}&libraries=places`,
      () => handleScriptLoad(setQuery, autoCompleteRef)
    );
  }, []);

  return (
    <div
      className="flex items-center w-full xl:w-1/3 h-12 mr-2 bg-gray-100 pl-3 rounded-none mb-2 lg:w-1/3 lg:mb-0"
      style={isSearchFocused ? { borderColor: "black", borderWidth: 2 } : {}}
    >
      <LocationIcon className="w-5 h-5 text-left" />
      <input
        placeholder="placeholder"
        ref={autoCompleteRef}
        onChange={(event) => setQuery(event.target.value)}
        value={query}
        className="w-full ml-3 bg-gray-100 h-11 font-poppins placeholder-black outline-none"
        onFocus={() => setIsSearchFocused(true)}
        onBlur={() => setIsSearchFocused(false)}
      />
    </div>
  );
};
0 Answers
Related