Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Design] Mobile ver. - Header 반응형 구현 #371

Merged
merged 25 commits into from
Aug 11, 2024

Conversation

lydiacho
Copy link
Member

@lydiacho lydiacho commented Aug 10, 2024

Related Issue : Closes #350


🧑‍🎤 Summary

헤더 반응형 구현했습니다

🧑‍🎤 Screenshot

2024-08-10.7.27.36.mov

🧑‍🎤 Comment

헤더를 처음에 작업하다가 이후 다른 페이지 작업으로 넘어가서 초반 commit이 좀 중복/충돌돼요 ㅜㅜ
merge ~ 커밋 이후부터 봐주시면 됩니다

작업 내용

1️⃣ TextBox이메일에서 width 처리 부족했던거 해결
로그인 반응형 PR에서 누락된 이메일 input width 처리

2️⃣ 달라진 useDevice 반환값에 따른 수정
useDevice 반환값이 isTablet, isMobile이 아닌 DEVICE_TYPE으로 바뀜에 따라 기존 작업물들 코드 조금 수정해줌

3️⃣ header position fixed로 수정 및 layout marginTop 추가
header position fixed로 바꿔주니까 header 높이만큼 페이지 레이아웃이 올라가서,
Layout의 wrapper 자체에 header height만큼 paddingTop을 추가해줌

4️⃣ header padding 반응형 (반응형 레이아웃)

  • 탭 : padding 22 40
  • 모바일 : padding 12 20

5️⃣ MenuList 컴포넌트 분리
MenuList가 header 안에서도 (데탑) 쓰이고, header의 외부에서도 다른 스타일로 (모바일/탭) 쓰여야 하므로 컴포넌트 분리시켜줌

  • MenuList.tsx : 모집공고, 로그아웃 등의 MenuItem 목록
  • Nav.tsx : Header 의 우측에 위치하는 컴포넌트 (MenuList가 될 수도 있고, 햄버거/클로즈 아이콘이 될 수도 있음)

6️⃣ 드롭메뉴 헤더 반응형

  • 로고와 햄버거 / 데탑nav 의 관계 : display flex, justify contents space between
  • 로고 &햄버거 와 메뉴리스트의 관계 : display flex, flex column
  • menuMobList 반응형
    • 탭 : padding 92 40 40 40
    • 모바일 : 86 20 36 20
  • menuItem 반응형
    • 데탑 : heading 18, baseText, Line active면 Primary, hover시 밑줄
    • 탭 , 모바일 : heading 18, gray300, hover시 gray10

7️⃣ DEVICE_TYPE에 따라 isMenuOpen값 초기화
TAB/MOB에서 메뉴를 열어둔 상태로 창 크기를 늘려 DESK 가 되었을 때 자동으로 드롭메뉴가 닫히도록 처리

8️⃣ Nav 조건부 렌더링 (menuList / 햄버거 / x버튼)

9️⃣ dimmed 배경 추가

  • dimmed 배경 클릭 시 헤더 닫히도록

🔟 애니메이션 추가

🚀 애니메이션 구현 관련

헤더와 backdrop은 fade in/out 으로,
드롭메뉴는 fade in + down, fade out + up 되도록 구현했어요 (공홈과 같은 방식)

항상 조건부렌더링 해주는 컴포넌트가 마운트될 때 / 언마운트될 때 애니메이션을 주는걸 opacity 등의 방편을 사용했었는데
이번에는 전체화면을 덮는 backdrop에 애니메이션을 줘야되다보니 opacity transition으로는 한계가 있었어요.

그래서 조건부렌더링 되는 척! 이 아니라, 실제로 조건부 렌더링도 되는 방식으로 다르게 구현했습니다.

이를 위해 MenuList에 isShown state와 animation state을 추가해주었어요,

  • isShown : 드롭메뉴 & backdrop 표시 여부
  • animation : 애니메이션을 부여해주는 styeVariant의 키값을 관리
  const [isShown, setIsShown] = useState(isMenuOpen);
  const [animation, setAnimation] = useState<'open' | 'close'>(isMenuOpen ? 'open' : 'close');

부모 컴포넌트인 Header에서 드롭메뉴 / backdrop 표시 여부를 관리해주는 state는 isMenuOpen이고,
이를 MenuList 컴포넌트에도 prop으로 전달하고 있어요.

MenuList에서 prop으로 받은 isMenuOpen 값과, isShown 값을 동기화시켜주어야 하는데요,
그럼 왜 같은 값을 가지는 애들이면 굳이 다른 state로 분리해서 관리하냐?
-> setMenuOpen(false)가 되면 곧바로 언마운트 되는 것이 아닌,
fadeOut & fadeOutUp 애니메이션을 먼저 실행시킨 후, 0.3초 후에 언마운트 시키기 위해서 입니다.

  useEffect(() => {
    if (isMenuOpen) {
      setIsShown(true);
      setAnimation('open');
    } else {
      setAnimation('close');
      const timer = setTimeout(() => setIsShown(false), 300);
      return () => clearTimeout(timer);
    }
  }, [isMenuOpen]);

따라서 이렇게 isMenuOpen 값이 바뀜에 따라

  • isMenuOpen이 true가 되면 (햄버거 아이콘 클릭)
    • 드롭메뉴 표시 (setIsShown(true))
    • fade in / fadeInDown 애니메이션 실행
  • isMenuOpen이 false가 되면 (클로즈 아이콘 클릭)
    • fade out / fadeOutUp 애니메이션 실행 (0.3초 동안)
    • 0.3초 후 드롭메뉴 언마운트 (setIsShown(false))

이런식으로 구현했습니다.

그런데 MenuList 컴포넌트는 데탑뷰 헤더 Nav모바일뷰 드롭메뉴가 공통으로 사용하고 있는 컴포넌트인데요,
따라서 컴포넌트 내부에서 isShown 값에 따라 조건부렌더링을 해줄 때 현재 이 컴포넌트가 데탑뷰 헤더 nav인지, 모바일뷰 드롭메뉴인지를 구분해서 렌더링 시켜줘야 해요.

이는 Header에서 햄버거/클로즈 아이콘 클릭 이벤트 핸들러(드롭메뉴를 껐켰하는 함수)를 optional prop으로 넘겨주는데,
해당 prop의 undefined 여부를 통해 구분시켜줍니다

if (onClickMenuToggle && !isShown) return null;
...
{onClickMenuToggle && isShown && <div className={dimmedBgVar[animation]} onClick={onClickMenuToggle} />}

+) 🙋🏻‍♀️ 제안

만들어놓은 fade in / out / inDown / outUp keyframes 들은 다른 곳에서도 추후 충분히 도입할 수 있는 애니메이션들이라고 생각해서,
src > styles 디렉토리에 animation.css.ts 만들어서 공용으로 분리시켜놔도 될 것 같은데 어떻게 생각하시나용?

Copy link

height bot commented Aug 10, 2024

Link Height tasks by mentioning a task ID in the pull request title or commit messages, or description and comments with the keyword link (e.g. "Link T-123").

💡Tip: You can also use "Close T-X" to automatically close a task when the pull request is merged.

Copy link
Member

@eonseok-jeon eonseok-jeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이전 커밋이 같이 딸려왔다면 rebase를 이용해서 정리해주시면 될 거 같아요~~
여기에 이용법 정리되어 있으니 참고해 보세요

고생하셨습니다~

만들어놓은 fade in / out / inDown / outUp keyframes 들은 다른 곳에서도 추후 충분히 도입할 수 있는 애니메이션들이라고 생각해서,
src > styles 디렉토리에 animation.css.ts 만들어서 공용으로 분리시켜놔도 될 것 같은데 어떻게 생각하시나용?

좋은 거 같아여 :)

@lydiacho
Copy link
Member Author

@eonseok-jeon 아 커밋이 딸려온게 아니라 실제로 중복되는 작업을 해줬다는 의미예요! 보시면 merge 앞에도 다 헤더와 관련된 작업입니다 (다른 브랜치와 다 다른 커밋) useDevice 만들어주는 작업이나 react-responsive 설치하는게 중복된 작업이었는데, 중간에 제가 develop Pull 한번 받으면서 싱크를 맞췄어서 현재는 conflict도 없고 문제 없을 것 같습니다:) 머지하겠습니다 !_!

@lydiacho lydiacho merged commit c26e2cd into develop Aug 11, 2024
@lydiacho lydiacho deleted the design/#350_mobile-header branch August 11, 2024 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Design] Mobile ver. - Header 구현
2 participants