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

[Feat] 홈 헤더 퍼블리싱 및 스크롤시 헤더 상태 변경 로직 구현 #63

Merged
merged 16 commits into from
Jan 16, 2025

Conversation

rtttr1
Copy link
Collaborator

@rtttr1 rtttr1 commented Jan 15, 2025

📌 Related Issues

✅ 체크 리스트

  • PR 제목의 형식을 잘 작성했나요? e.g. [Feat] PR 템플릿 작성
  • 빌드가 성공했나요? (pnpm build)
  • 컨벤션을 지켰나요?
  • 이슈는 등록했나요?
  • 리뷰어와 라벨을 지정했나요?

📄 Tasks

  • 홈 화면 헤더 퍼블리싱
  • 스크롤 시 헤더 상태 변경 로직 구현 (useIntersect 훅 구현)

⭐ PR Point (To Reviewer)

useIntersect 훅

import { MutableRefObject, useCallback, useEffect, useRef, useState } from 'react';

export const useIntersect = (initialVisible: boolean, options?: IntersectionObserverInit) => {
  const ref = useRef<HTMLDivElement>(null);

  const [isVisible, setIsVisible] = useState(initialVisible);

  const callback = useCallback((entries: IntersectionObserverEntry[]) => {
    entries.forEach((entry) => {
      setIsVisible(!entry.isIntersecting);
    });
  }, []);

  useEffect(() => {
    if (!ref.current) return;

    // 이미지 영역에서 헤더 높이를 제외한 비율값
    const threshold = 1 - (ref.current?.offsetHeight - 60) / ref.current?.offsetHeight;

    const observer = new IntersectionObserver(callback, { ...options, threshold: threshold });
    observer.observe(ref.current);
    return () => observer.disconnect();
  }, [ref, options, callback]);

  return [ref, isVisible] as [MutableRefObject<HTMLDivElement | null>, boolean];
};

헤더가 이미지를 벗어나면 색상이 바뀌어야 합니다. 이 로직을 구현하기 위해 IntersectionObserver 를 사용하였습니다. 자세한 사용법은 잘 작성되어있는 아티클 참고해주세요!

제가 구현한 훅의 사용법은 다음과 같습니다.
useIntersect에 isVisible 상태의 초기값을 넣어줍니다. 반환값은 targetRef, isVisible 두개의 값을 반환합니다.

  • targetRef: 화면에서 안보이게 되는 시점에 isVisible 값을 변경시켜줄 컴포넌트에 집어넣는 ref 입니다.
  • isVisible: 값에 따라서 헤더의 스타일을 변경해주면 됩니다.
const Home = () => {
  const [targetRef, isVisible] = useIntersect(false);

  return (
    <div style={{ height: '300rem' }}>
      <div ref={targetRef} style={{ height: '37.5rem', backgroundColor: vars.colors.gray02 }}></div>
      <HomeHeader isVisible={isVisible}></HomeHeader>
    </div>
  );
};

저희 뷰에서는 이미지가 안보이는 시점에 헤더의 스타일이 변합니다. 따라서 이미지 혹은 이미지를 감싸주는 컴포넌트에 targetRef를 넣어주고 isVisible로 헤더의 스타일을 분기처리해주면 간단하게 로직을 적용시킬 수 있습니다~!

📷 Screenshot

2025-01-16.1.23.58.mov

🔔 ETC

@rtttr1 rtttr1 added 🛠️ Feature 기능 개발 규홍 슈퍼주니-어에요 labels Jan 15, 2025
@rtttr1 rtttr1 self-assigned this Jan 15, 2025
Copy link
Collaborator

@hansoojeongsj hansoojeongsj left a comment

Choose a reason for hiding this comment

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

우왕........... 👍

Copy link
Collaborator

@heesunee heesunee left a comment

Choose a reason for hiding this comment

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

이걸 해낸 당신은 천재 개발자 ... 진짜 멋있다 , , , ,,,,,,, 스크롤할 때 더 간지날듯 ㅋㅋ 아침까지 잠도 안자고 너무 고생하셨어요 .... 코멘트 남긴 부분만 확인해주세요 !

Comment on lines 32 to 35
export const iconsStyle = style({
display: 'flex',
gap: '2rem',
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

이거 사용되고 있는 부분이 있나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Flex 버그 있을때 잠깐 사용했던 건데 지워야갰네요!

Comment on lines 7 to 9
export const imageStyle = style({
height: '50rem',
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

이거도 사용되고 있는 부분이 있나요?

Comment on lines +9 to +12
<div style={{ height: '300rem' }}>
<div ref={targetRef} style={{ height: '37.5rem', backgroundColor: vars.colors.gray02 }}></div>
<HomeHeader isVisible={isVisible}></HomeHeader>
</div>
Copy link
Collaborator

Choose a reason for hiding this comment

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

인라인 스타일 대신 css 파일에 따로 써서 적용하는 게 좋을 듯 합니다 !

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

캐러셀 넣기전에 임시로 넣어둔 부분이라 홈 화면 퍼블리싱 할때 지우겠습니다!

Copy link
Collaborator

Choose a reason for hiding this comment

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

진짜 멋있다 ... 덕분에 스크롤할 때 더 기깔나겠어요,.. 👍

Copy link
Member

@KIMGEONHWI KIMGEONHWI left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! 코리 한번만 확인해주세요.

Comment on lines +18 to +36
<Flex tag="header" className={containerStyle({ isVisible })}>
{isVisible ? (
<>
<IcLogoSmallBlack width={54} height={18} />
<Flex gap="2rem">
<IcSearchBlack24 width={24} height={24} />
<IcMypageBlack24 width={24} height={24} />
</Flex>
</>
) : (
<>
<IcLogoSmallWhite width={54} height={18} />
<Flex gap="2rem">
<IcSearchWhite24 width={24} height={24} />
<IcMypageWhite24 width={24} height={24} />
</Flex>
</>
)}
</Flex>
Copy link
Member

Choose a reason for hiding this comment

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

현재 아이콘의 색상만 변경되고 있으니 새로운 아이콘을 렌더링 해주는 것이 아니라, 기존의 아이콘에 색상을 주입해서 사용하면 불필요한 svg파일 용량도 줄일 수 있을 것 같습니다!!

Copy link
Collaborator

@constantly-dev constantly-dev left a comment

Choose a reason for hiding this comment

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

스크롤에 따라 스타일 분기하는 것이 쉽지 않았을텐데 수고하셨습니다!

Comment on lines +21 to +24
<IcLogoSmallBlack width={54} height={18} />
<Flex gap="2rem">
<IcSearchBlack24 width={24} height={24} />
<IcMypageBlack24 width={24} height={24} />
Copy link
Collaborator

Choose a reason for hiding this comment

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

물론 명시적으로 작성하실 수도 있지만 tsx로 변환된 svg파일에 width값만 줘도 비율에 맞게 조정되니 width값 하나만 줘도 괜찮을 것 같습니다!

@rtttr1 rtttr1 merged commit 78a8b46 into develop Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 16, 2025
rtttr1 added a commit that referenced this pull request Jan 17, 2025
rtttr1 added a commit that referenced this pull request Jan 17, 2025
rtttr1 added a commit that referenced this pull request Jan 17, 2025
rtttr1 added a commit that referenced this pull request Jan 17, 2025
rtttr1 added a commit that referenced this pull request Jan 17, 2025
[Feat] 홈 페이지 가로스크롤 및 케러셀 제외 뷰 구현
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
규홍 슈퍼주니-어에요 🛠️ Feature 기능 개발
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feat] 홈 페이지 퍼블리싱
5 participants