TIL.png


์˜ค๋Š˜ํ•œ์ผ ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป .

  1. ๋ฉด์ ‘์ค€๋น„ ๐Ÿ”ฅ
  2. ์ฝ”๋”ฉํ…Œ์ŠคํŠธ โš™๏ธ

๊ธฐ๋ก โœ๐Ÿป .

  • ์ด๋ ฅ์„œ๋ฅผ ์ œ์ถœํ•œ ํšŒ์‚ฌ์—์„œ ์—ฐ๋ฝ์ด ์™”๋‹ค. ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ…Œ์ŠคํŠธ๊ฐ€ ์•„๋‹Œ ์‹ค๋ฌด์— ๊ฐ€๊นŒ์šด ๋‚ด์šฉ์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ณผ์ œ ๋А๋‚Œ ํ”ผ๊ทธ๋งˆ url๊ณผ json ํŒŒ์ผ์„ ๋ฉ”์ผ๋กœ ๋ฐ›์Œ ํ”ผ๊ทธ๋งˆ ๋‚ด์šฉ๋Œ€๋กœ ๋ทฐ ์ž‘์—…๋ถ€ํ„ฐ ์ง„ํ–‰ํ–ˆ๋‹ค

22_02_15_img_2.png


ํ”„๋กœ์ ํŠธ ํด๋” ๊ตฌ์กฐ

App.js์— Navigation ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉ, Navigation ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ MobileMenu๋ฅผ ๋ชจ๋‹ฌ ํŒ์—… ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ


22_02_15_img.png

  • ์ฃผ์–ด์ง„ ์กฐ๊ฑด ์ค‘ ๋ฐ˜์‘ํ˜•์„ ์ ์šฉํ•˜์—ฌ ๋ชจ๋ฐ”์ผ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋˜์—ˆ์„ ์‹œ ์ƒ๋‹จ์˜ ๋„ค๋น„๊ฒŒ์ด์…˜์ด ํ–„๋ฒ„๊ฑฐ ๋ฉ”๋‰ด ๋ฒ„ํŠผ๊ณผ ๋กœ๊ณ ๋งŒ ๋‚จ๊ณ  ํ–„๋ฒ„๊ฑฐ ๋ฉ”๋‰ด ๋ฒ„ํŠผ์„ ํด๋ฆญ ์‹œ ์ขŒ์ธก์—์„œ ์šฐ์ธก์œผ๋กœ fade-in ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ ์šฉํ•˜๋Š” ์กฐ๊ฑด์ด ์žˆ์–ด ์ด ์ž‘์—…๋ถ€ํ„ฐ ์ง„ํ–‰ํ•จ, ์ถ”๊ฐ€์ ์œผ๋กœ ํ–„๋ฒ„๊ฑฐ ๋ฉ”๋‰ด๊ฐ€ ๋‚˜์˜ฌ ์‹œ ์šฐ์ธก ๋นˆ ์—ฌ๋ฐฑ์„ ํด๋ฆญํ•˜์—ฌ ํ–„๋ฒ„๊ฑฐ ๋ฉ”๋‰ด๋ฅผ ๋‹ซ๋Š” ๊ธฐ๋Šฅ๊นŒ์ง€ ์ถ”๊ฐ€ํ•จ

22_02_15_gif.png


  • ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ style-component, @media screen๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€๋กœ๊ฐ’์ด 500px์ด ๋˜์—ˆ์„๋•Œ ๋ชจ๋ฐ”์ผ ๋ฉ”๋‰ด๋กœ ๋ณ€๊ฒฝ
      const NavBox = styled.div`
        @media screen and (max-width: 500px) {
          #mb_menu {
          display: none;
          margin-right: 19px;
        }

        @media screen and (max-width: 500px) {
          width: 100%;
          padding-left: 23px;

          #ateam_logo {
            width: 91.8px;
            height: 12px;
          }
          #mb_menu {
            display: block;
          }
        }
      ` 
      const AnotherBox = styled(LogoBox)`
        justify-content: flex-end;
        padding-left: 0;
        padding-right: 40px;

        @media screen and (max-width: 500px) {
          display: none;
        }
      }
    `

  • Navigation ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฐ์Šคํฌํƒ‘ ์‚ฌ์ด์ฆˆ์—์„œ ๋…ธ์ถœ๋œ๋‹ค. MobileMenu ์ปดํฌ๋„ŒํŠธ๋Š” ๋ชจ๋ฐ”์ผ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋˜์—ˆ์„ ์‹œ display: bolck์„ ์‚ฌ์šฉํ•˜์—ฌ ๋…ธ์ถœ์‹œ์ผœ์ฃผ๋ฏ€๋กœ ๊ฐ์ž ์ •ํ•ด์ง„ ๊ฐ€๋กœ ๊ฐ’์— ๋ฐ˜์‘ํ•˜์—ฌ ๋…ธ์ถœ๋œ๋‹ค. ๋ชจ๋ฐ”์ผ ๋ฉ”๋‰ด๋Š” Navigation ์ปดํฌ๋„ŒํŠธ์—์„œ useState๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋‰ด ์˜คํ”ˆ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋ฉฐ props๋กœ MobileMenu ์ปดํฌ๋„ŒํŠธ์— openModal ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ๋ชจ๋ฐ”์ผ ๋ฉ”๋‰ด ํด๋ฆญ ์‹œ useState ์ƒํƒœ ๊ฐ’์„ ture๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ฉ”๋‰ด๋ฅผ ์˜คํ”ˆํ•œ๋‹ค. ๋ชจ๋ฐ”์ผ ๋ฉ”๋‰ด ์˜์—ญ ๋ฐ–์„ ํด๋ฆญ ์‹œ useEffect๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ โ€œmousedowโ€ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  handleClickOutside ํ•จ์ˆ˜๋กœ ๋ชจ๋ฐ”์ผ ๋ฉ”๋‰ด ์ƒํƒœ ๊ฐ’์„ false๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ฉ”๋‰ด๋ฅผ ๋‹ซ๊ฒŒ ํ•˜๊ณ  useRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Navigation ์ปดํฌ๋„ŒํŠธ ์˜์—ญ์„ ์„ค์ •
Navigation.js

const Navigation = () => {
  const wrapperRef = useRef();
  const [modalOpen, setModalOpen] = useState(false);
  const openModal = () => {
    setModalOpen(true);
  };
  useEffect(() => {
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  });

  const handleClickOutside = (event) => {
    if (wrapperRef && !wrapperRef.current.contains(event.target)) {
      setModalOpen(false);
    }
  };

  return (
    <>
      <NavBox ref={wrapperRef}>
        {/* ๋ฐ์Šคํฌํƒ‘ ๋„ค๋น„๊ฒŒ์ด์…˜ */}
        <LogoBox>
          {/* ๋ชจ๋ฐ”์ผ ๋„ค๋น„๊ฒŒ์ด์…˜ */}
          <MobileMenuBar id="mb_menu" onClick={openModal} />
          <AteamLogo id="ateam_logo" />
        </LogoBox>
        <AnotherBox>
          <BtnTwo>
            <NavIcon fill="#fff" />
            <NavText>A ๊ฐ€๊ณต ์—…์ฒด</NavText>
          </BtnTwo>
          <Line />
          <LogOutBtn>๋กœ๊ทธ์•„์›ƒ</LogOutBtn>
        </AnotherBox>
      </NavBox>
      <MobileMenu open={modalOpen} />
    </>
  );
};
MobileMenu.js
const MobileMenu = (props) => {
  const { open } = props;
  return (
    <>
      <ModalBox className={open ? "openModal modal" : "modal"}>
        {open ? (
          <ModalBackground>
            <ModalContents>
              <ModalHead>
                <LogoBlue />
              </ModalHead>
              <ModalBody>
                <BtnTwo>
                  <NavIcon fill="#323D45" />
                  <NavText>A ๊ฐ€๊ณต ์—…์ฒด</NavText>
                </BtnTwo>
                <LogOutBtn>๋กœ๊ทธ์•„์›ƒ</LogOutBtn>
              </ModalBody>
            </ModalContents>
          </ModalBackground>
        ) : null}
      </ModalBox>
    </>
  );
};

  • ๋ชจ๋ฐ”์ผ ๋ฉ”๋‰ด ์˜คํ”ˆ ์‹œ ์ขŒ์ธก์—์„œ ์šฐ์ธก์œผ๋กœ ๋ฐ€๋ ค๋“ค์–ด์˜ค๋Š” fade-in ์—๋‹ˆ๋ฉ”์ด์…˜๊ณผ ๋ฉ”๋‰ด ๋’ท๋ฐฐ๊ฒฝ ์—๋‹ˆ๋ฉ”์ด์…˜์€ @keyframes์„ ์‚ฌ์šฉํ•˜์—ฌ ์ ์šฉ
- ๋’ท๋ฐฐ๊ฒฝ ์—๋‹ˆ๋ฉ”์ด์…˜

const ModalBackground = styled.div`
  width: 100%;
  height: 100vh;
  overflow: hidden;
  background-color: rgba(50, 61, 69, 0.5);
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9;

  animation: fadeInBackground 0.35s;

  @keyframes fadeInBackground {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
`;
- ์ขŒ์ธก์—์„œ ์šฐ์ธก์œผ๋กœ ์—๋‹ˆ๋ฉ”์ด์…˜

const ModalContents = styled.div`
  width: 75%;
  height: 100vh;
  overflow: hidden;
  background-color: #fff;
  animation: fadeInModal 0.45s;

  @keyframes fadeInModal {
    from {
      opacity: 0;
      margin-left: -600px;
    }
    to {
      opacity: 1;
      margin-left: 0;
    }
  }
`;

๋‚ด์ผ์€ toggle ๋ฒ„ํŠผ ์ž‘์—… ๐Ÿ”ฅ