0

I am trying to use Tippy.js to render a detailPopup card component whenever the user clicks on an icon. works normally but it seems like the detail component is being rendered on top of another content by Tippy thereby causing an overlap. As shown here in the image you can see the overlap. Thats really not what I want..

This is the component that renders the popup and Tippy.

import { FaCircle } from "react-icons/fa";
import { Cast, Crew } from "./PeopleType";
import { Link } from "react-router-dom";
import { DetailPopUp } from "./DetailPopUp";
import { useState } from "react";

// import Tippy from "@tippyjs/react/headless";
import Tippy from "@tippyjs/react";
import "tippy.js/dist/tippy.css";

type CreditListProps = {
  credit: Cast[] | Crew[];
};

export function CreditList({ credit }: CreditListProps) {
  const [selectedItemId, setSelectedItemId] = useState<number | null>(null);

  function togglePopup(itemId: number) {
    setSelectedItemId(itemId);
  }

  function getYearOrUnderscore(dateString: string) {
    if (!dateString) {
      return "-----";
    }
    return new Date(dateString).getFullYear();
  }

  function isCast(credit: Cast | Crew): credit is Cast {
    return (credit as Cast).character !== undefined;
  }

  function isCrew(credit: Cast | Crew): credit is Crew {
    return (credit as Crew).job !== undefined;
  }

  const sortedData = credit.sort((a, b) => {
    const yearA = getYearOrUnderscore(
      a.media_type === "tv" ? a.first_air_date : a.release_date
    );
    const yearB = getYearOrUnderscore(
      b.media_type === "tv" ? b.first_air_date : b.release_date
    );

    if (yearA === "-----" && yearB === "-----") {
      return 0;
    }
    if (yearA === "-----") {
      return -1;
    }
    if (yearB === "-----") {
      return 1;
    }
    return yearB - yearA;
  });

  let currentYear: string | number | null = null;

  return (
    <>
      {sortedData.map((credit) => {
        const year = getYearOrUnderscore(
          credit.media_type === "tv"
            ? credit.first_air_date
            : credit.release_date
        );

        const hrElement = year !== currentYear ? <hr key={year} /> : null;
        currentYear = year;

        return (
          <>
            {hrElement}
            <div className="flex gap-4 p-4 items-center" key={credit.id}>
              <p>{year}</p>
              <Tippy
                visible={selectedItemId === credit.id}
                onClickOutside={() => setSelectedItemId(null)}
                arrow={true}
                interactive={true}
                content={
                  <div>
                    <DetailPopUp credit={credit}></DetailPopUp>
                  </div>
                }
                inlinePositioning={true}
              >
                <div className="text-xs rounded-full border border-black group cursor-pointer ">
                  <FaCircle
                    className="text-white group-hover:text-blue-800 p-0.5"
                    size={8}
                    onClick={() => togglePopup(credit.id)}
                  />
                </div>
              </Tippy>
              <p className="font-light text-[#7f7f7f]">
                {" "}
                <Link to={`/${credit.media_type}/${credit.id}`}>
                  <span className="text-black font-bold hover:text-blue-400 cursor-pointer">
                    {credit.media_type === "tv" ? credit.name : credit.title}
                  </span>
                </Link>{" "}
                {credit.media_type === "tv" && (
                  <span className="hover:text-blue-400 cursor-pointer">
                    ( {credit.episode_count}{" "}
                    {credit.episode_count === 1 ? "episode" : "episodes"} )
                  </span>
                )}
                {isCast(credit) && (
                  <>
                    {credit.character && (
                      <>
                        <span> as </span>
                        <span className="text-black">{credit.character}</span>
                      </>
                    )}
                  </>
                )}
                {isCrew(credit) && (
                  <>
                    {credit.job && (
                      <>
                        <span> ...</span>
                        <span className="text-black">{credit.job}</span>
                      </>
                    )}
                  </>
                )}
              </p>
            </div>
          </>
        );
      })}
    </>
  );
}

And this is the DetailPopup component.

import { FaBookmark, FaHeart, FaStar } from "react-icons/fa";
import { Cast, Crew } from "./PeopleType";

type DetailPopUpProps = {
  credit: Cast | Crew;
};

export function DetailPopUp({ credit }: DetailPopUpProps) {
  const API_IMG = "https://image.tmdb.org/t/p/w500";

  const words = credit.overview.split(" ");
  const truncated = words.slice(0, 18).join(" ");

  const truncatedWithEllipsis =
    words.length > 18 ? truncated + " ..." : truncated;

  return (
    <>
      {credit && (
        <div className="w-[535px] h-[170px] bg-[#032541] rounded-md text-white">
          <div className="px-3 pt-3 pb-6 flex gap-4 items-start">
            <figure className="h-[140px] w-[100px] min-w-[95px] rounded-lg overflow-hidden cursor-pointer">
              <img
                src={API_IMG + credit.poster_path}
                alt=""
                className="w-full h-full"
              />
            </figure>
            <div>
              <div>
                <div className="flex items-center gap-3">
                  <h2 className="font-bold text-xl">
                    {credit.media_type === "tv" ? credit.name : credit.title}
                  </h2>
                  <div className=" bg-blue-500 rounded-md flex gap-2 py-1 px-2 items-center">
                    <FaStar className="" /> {credit.vote_average.toFixed(1)}
                  </div>
                </div>
                <p className="py-5">{truncatedWithEllipsis}</p>
                <ul className="flex gap-3 items-center text-base">
                  <li className=" bg-blue-500 p-4 rounded-md hover:bg-slate-600">
                    <a href="">
                      <FaHeart />
                    </a>
                  </li>
                  <li className=" bg-blue-500 p-4 rounded-md hover:bg-slate-600">
                    <a href="">
                      <FaBookmark />
                    </a>
                  </li>
                  <li className=" bg-blue-500 p-4 rounded-md hover:bg-slate-600">
                    <a href="">
                      <FaHeart />
                    </a>
                  </li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

I have tried using Headless Tippy but couldn't figure out how to position the arrow and flip it when the position of the popup is flipped. This is the intended result

applesomthing
  • 361
  • 3
  • 19

0 Answers0