2023.11.03 헤더 부분완성

이무헌·2023년 11월 3일
0

block explore

목록 보기
1/6
post-thumbnail

1.header 코드


"use client";
/* eslint-disable @next/next/no-img-element */
// eslint-disable-next-line @next/next/no-img-element
import { Disclosure, Menu, Transition } from "@headlessui/react";
import { Fragment, useEffect, useRef, useState } from "react";

import React from "react";
import DropDownMenu from "./dropDownMenu";

const Header = () => {
  const open = "w-full h-56 border-2 border-black";
  const close =
    "w-full h-16 flex justify-between items-center border-2 border-black";
  const [isRendered, setIsRendered] = useState<boolean>(false);
  const [isMenuOpen, setIsMeuOpen] = useState<boolean>(false);
  useEffect(() => {
    setIsRendered(true);
  }, []);
  return (
    <>
      {isRendered && (
        <div className="w-full h-fit relative ">
          <div className=" w-full h-full flex justify-between items-center relative z-10 bg-white  ">
            <div className="w-2/5 h-10 flex justify-between items-center">
              <img
                src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEMUlEQVR4Ae2WA5DkWhSGszbGSjpp2/batm3btm3vs23btm379fC8v1IvO1Zmy3OrvkH3yfmPcu9l6lf9qstq2rhxS4NO18eo148TFAo1PmrctnVrVuC4dLVS2aCkrZLnm4MWl0UYjhqnJCWld+3cecfJEycSPXv0IC4n541oOHxq6pQpH+m12tcQUJ//bRsCo6DgNTzHu4lyGtHnbAO5wklgDLie57i3d+/alfjpp5+of79+lJWRQZMnTaK7776btGo1IYCHVYLQisGCuKBW8uOuOcSdLvqUvZM+YwfKEbeDe0EeEEXugVgikaATJ06Qz+ulMaNH09tvv01TJk8mi8n0NVoxF7YjkPnwoIff/uET7K/0JUv5n7APPXwN16o24hbwCqCSXLxwgfLz8+mvv/6iV199lWbOmEEvvvAC3XfvveRHQKgCwa4QFGmUPO1fr0j88Tb7xdUHuftUAj9U4PloTcTbgtvLiqMF1KdXL3r6qafos88+oxPHj5PJYCCfx0NOu120KYtOzT+xZ43CqNfwU9GWCD7LqkkA46Wyl0HM0AGxWCRCOo1G/F+iInuwrERSnUDr6sTbgEcAVQbExGrg7+p4EyhL+G4EGlQXQAz8AaiO/ABkTf4aQHXkPTAINKiteFNwp0zRIkz4h2jPDqBh5Cy9RqOGo49kiGPa1X/4HI7NHQIBV5dwOAm/G9ZIFIatQKRjMLgJDp7GTpZfW3EB2E2moo6BQD58/QJeBafAUJBZmXAz0A/cA34H5LZaZfVcAFajkeCjLHngdbAUZJQUTwH7wV+AJKwGg+hMZgvI73BQBJtS3O8vG0gheBy4pABOgAJAcRDCQy5kr1Wp6jT9aB9p4MOo1ZLDbKaA00mx0sE8AxSMlHnA5SILssY5Lm0wssXLblKSLwOC8dhsUiB5YDwT8/m+closBGHREPu5GLkVUSML0UEthUVfQPQVi0ZFX163+1IgJr2ewh7PnxjU/ozNaJwMoW/xJQV8PpozezbhUkHbtm6lPr170yyccDh6a5W1HS3ct3cvjR41ik6dOkWzZ86kdWvXksvhkILIRzWOdg6HWzNsTk5DfNCRzc5+YgouFAvmz6ebb7qJZuGhxx59lBYvXFjbdoj2a1evpvvvv198/uyZM7R2zRrx9FSw7CewmQ+b0gdRanKyb8SwYT9PmzqVzp87J1bi3nvuIbPRKCcAseR33nGHWEHcnGj6tGkUCYVez87MtFa4LacmJbVAr64KYkAmT5xIo0aMELOAsx/xwE8gF1ANKAB/4F74D7KnXj17UreuXQtsFssvmIsJTFULF0sOJVqIs/1B3HS/xuUiD84WAgvoBSaBZWAz2AP2g31gO1gNZoEhwA+x3biWfYX5egBJrIRvP3w3ZWqyMA9JMDaAYXCWwchYEG0PUT18tGCzsio9C+pX/foPmawbnhEQly8AAAAASUVORK5CYII="
                alt="바운스코드 이미지"
                className="ml-2"
              />
              <div>Bounce Code</div>
            </div>

            <div className=" top-16 w-14 text-right ">
              <img
                className="w-10  "
                src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/1200px-Hamburger_icon.svg.png"
                alt="메뉴 버튼"
                onClick={() => {
                  console.log(isMenuOpen);
                  setIsMeuOpen((prev) => {
                    return !prev;
                  });
                }}
              />
            </div>
          </div>
          <DropDownMenu isMenuOpen={isMenuOpen} />
        </div>
      )}
    </>
  );
};

export default Header;

  • 위에서 아래로 자연스럽게 내려와야 하는 애니메이션을 만들어야 했으며 서브 메뉴도 눌렀을 시 밑으로 내려가도록 했어야 했다.

  • 기존에 있던 방식으론 tailwind.config에서 애니매이션을 직접 추가해줬다! transformY를 이용해서 위에서 아래로 내려오게 하는것이다

  • 하지만 이렇게 할 경우 z-index가 적용되지 않는다!

  • 그러므로 margin-top으로 위에 존재하게하여 transition을 통해 자연스럽게 margin-top을 조정하여 내려오게 만들었다.

  • background color도 꼭 설정해주자! 안 그러면 z-index가 의미 없다.(그 태그에 존재하는 객체에서만 가려진다...)

2.DropDown 컴포넌트


"use client";

import Image from "next/image";
import React, { useEffect, useState } from "react";

interface IopenToggle {
  openToggle: boolean;
  key: string;
}
// 서브메뉴 인터페이스
interface IsubMenu {
  0: Array<string>;
  1: Array<string>;
  2: Array<string>;
  [key: number]: Array<string>;
}
const DropDownMenu = ({ isMenuOpen }: { isMenuOpen: boolean }) => {
  // 서브 메뉴를 열기위한 토글
  const [isSubMenuOpen, setIsSubMenuOpen] = useState<IopenToggle>({
    openToggle: false,
    key: "",
  });
  const subMenuCSS = "";
  const dropArray =
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAHlBMVEX///8AAABhYWFZWVleXl5bW1uZmZlWVlZSUlKHh4c7NRlEAAACq0lEQVR4nO3Za47jIBBFYc/E6XTvf8MjVEITx3kYTFGPPt8KfMUh/MiyAAAAAAAAAAAAAAAAAAAAAAAAYOPr9jez29eyfP/J7Luc4mr9FYpWCTXvxLXexYv1lyi5/P+5uVp/i4rr/S9qxlDXZSPfKV6XB9nu4uVxYLZQ1/3AXBOfDswU6pNEc018OTBLqC8SFRkejd0zkS3UN4nmOMUPJxj/Lr69gxlC/Zho9IkHB8YN9VCikSc2DIwZ6uFEo05sHBgv1KZERayn/8BDvxcp1OZEo51i1wkWUe5ixx2sYoTamWiciacGRgj1RKIxJp4e6D3Uk4kKz49G9zOx5TfUAYkKr6c46AQLn3dxyB2sPIY6LFGvEwcP9Bfq0EQ9TlQY6CvU4Yl6m6g00E+oKokKH0//wId+z0OoaokK+1AVE/UxUX2gdajKidpPnDLQMtQJidpOnDbQKtRJiQqLp1/1od+bH+rERMXsU5x8gsXcuzj1DlYzQ52e6OyJRgPnhWqS6MyJhgPnhGqWqNB/NAyeiS3tUE0TFbqnaH6CheZdNL6DlV6oDhIVWhPdDNQK1Umi4qYw8GY9amt8qI4SFaMnuhs4+i66uoPVyKffxUO/Ny5Uh4mKUafo9ASLMXfR5R2sRoTqNlFxfqLzgedDdZ2oODcxwMBzobpPVPQ/Go6fia3eUEMkKvpOMcwJFj13McgdrNpDDZSoaJ0YbmBrqMESFS0TQw5sCTVgouLooxHqmdg6FmrQRMWRUwx8gsXnuxj2DlafQg2dqHg/McHA9/9pOPtvotfruxj+DlavQk2RqHg+MdHA56GmSVTsn/7gD/3eY6ipEhXX3CdY3N/FZHewWjMnKtbsA2uoSRMVl+wDS6iJExU/1h8AAAAAAAAAAAAAAAAAAAAAAADw2/0D1Ro1Y8h9PUkAAAAASUVORK5CYII=";
  //  서브 메뉴 토글 handler
  const subMenuHandler = (key: string) => {
    setIsSubMenuOpen((prev) => {
      if (prev.key === key) {
        return {
          openToggle: !prev.openToggle,
          key: "",
        };
      } else {
        return {
          openToggle: !prev.openToggle,
          key,
        };
      }
    });
  };
  const menuCloseCSS = "h-fit p-1 mt-2 relative transition-all  -mt-40 z-00 ";
  const menuOpenCSS = "h-fit p-1 mt-2 relative transition-all  z-00 ";
  const menuArr: Array<string> = ["Blockchain", "Tokens", "NFTs"];
  const subMenuArr: IsubMenu = {
    0: ["Transactions", "Pending Transactions", "View Blocks"],
    1: ["ERC20 token transfer"],
    2: ["Latest Transfer", "Latest Mints"],
  };
  useEffect(() => {
    const temp = { ...isSubMenuOpen };
    temp.openToggle = false;
    setIsSubMenuOpen(temp);
  }, [isMenuOpen]);
  return (
    <div className={isMenuOpen ? menuOpenCSS : menuCloseCSS}>
      <ul className="w-full ">
        <li className="text-blue-400 mt-2">Home</li>
        {menuArr.map((el, index) => {
          return (
            <li
              className="w-full mt-2  "
              onClick={() => {
                subMenuHandler(index.toString());
              }}
              key={index}
            >
              <div className="flex justify-between items-center">
                {el}
                <Image
                  className={
                    isSubMenuOpen && isSubMenuOpen.key === index.toString()
                      ? ""
                      : "scale-y-[-1]"
                  }
                  width={10}
                  height={10}
                  src={dropArray}
                  alt="array"
                />
              </div>
              {isSubMenuOpen.openToggle &&
                isSubMenuOpen.key === index.toString() && (
                  <div className=" h-fit">
                    <div className="w-11/12 border-2 rounded-xl border-gray-100 h-fit m-auto p-5">
                      <ul>
                        {subMenuArr[`${index}`].map((el, index) => {
                          return <li key={index}>{el}</li>;
                        })}
                      </ul>
                    </div>
                  </div>
                )}
            </li>
          );
        })}

        <li className="text-blue-400 mt-2">NickName</li>
      </ul>
    </div>
  );
};

export default DropDownMenu;

  • 리스트들을 만들어 사용자에게 메뉴처럼 보여주기만 하면 된다.

  • 해당하는 메뉴를 누르면 그 메뉴에 해당하는 서브메뉴를 보여줘야 하므로
    객체형식으로 서브메뉴를 저장하고 key값을 해당하는 map함수의 index와 동일하게 가져갔다!

  • 서브메뉴가 열린 상태에서 메뉴를 누르면 서브메뉴가 열린상태에서 -mt-40이 적용되므로 서브메뉴 만큼 헤더밖을 넘어가는 현상이 일어난다.

  • 때문에 useEffect로 isMenuOpen 을 dependency로 주어 isSubMenuOpen의 openToggle을 false로 변경시켜준다.

3.자체 피드백

transform에서 메뉴가 헤드위로 이동하는 것을 z-index로 조정할려고 별의별 짓을 다 했다. absolute로도 바꿔보고 부모를 만들어 해당하는 element에 z-index를 주기도 했다. 결국 애니메이션에서 발생한 문제임을 알고 빠르게 margin과 transition으로 빠르게 바꾸길 잘 했다.
stack context개념을 잘 숙지하여 z-index 오류를 줄이도록 하자

profile
개발당시에 직면한 이슈를 정리하는 곳

0개의 댓글