상품 상세페이지 열기/접기 만들기

지원·2023년 8월 26일
3
post-custom-banner

커머스 사이트의 상품 상세페이지 이미지는 보통 길다.
그리고 상세 페이지 아래 공통으로 안내되는 사항이 있는데, 이를 보기 위해서는 상세페이지 이미지를 모두 스크롤을 해야한다는 불편함도 있다.
그래서 대부분의 커머스 사이트에는 상세페이지 열기/접기 버튼이 있고 이번에 이 내용을 구현해보았다.

우선 필요한 내용을 정리해 보면

  1. useState로 상세 페이지가 열려있는지 닫혀있는지 boolean값 관리
  2. 버튼을 클릭했을 때 boolean 값을 current 값의 반대로 바꾸어 주어야함
  3. 닫힌지/열린지에 따라 CSS를 사용하여, 아랫부분 이미지가 안보이는지/보이는지 효과를 주어야 함.

컴포넌트 구조

이렇게 DetailDescription이라는 컴포넌트를 만들어 보자.

DetailDescription에는 DetailImage가 들어가고, 그 아래에 상세 설명 닫기/열기 버튼을 넣어 줄 것이다.

이미지 자체에 CSS를 주기보다, ImageWrapper로 한번 DIV로 감싸서 Wrapper에 효과를 주는 것이 좋다. 이미지가 여러장이 될 수도 있고, 이미지가 아닌 다른 text가 들어갈 수도 있으므로

const DetailDescription = ({ productKey, detailImage, colorChartImage }: P) => {
  
  // detail이 열린지, 닫힌지 상태 관리 (초기값은 false로 닫힌 상태로 둔다)
  const [isDetailOpen, setIsDetailOpen] = useState(false);
  
  // 더보기 혹은 닫기 버튼을 클릭했을 때 이전 상태의 반대값으로 설정
  const handleMoreInfoClick = () => {
    setIsDetailOpen((prev) => !prev);
  };
  return (
    <Container>
      <ImageWrapper isOpen={isDetailOpen}>
    // overlay는 자연스럽게 연결되는 효과를 주기 위해서 추가함 (아래에 설명)
        {!isDetailOpen && <OverLay />}
        <AutoHeightImage
          src={detailImage}
          alt={productKey}
          sizes="100vh"
        />
        <AutoHeightImage
          src={colorChartImage}
          alt={productKey}
          sizes="100vh"
          loading="lazy"
        />
      </ImageWrapper>
      <OpenButton onClick={handleMoreInfoClick}>
        {isDetailOpen ? "상품 상세 닫기" : "상품 상세 더보기"}
      </OpenButton>
    </Container>
  );
};

export default DetailDescription;

styling

이 기능은 CSS 코드가 중요하다.
isDetailOpen을 props로 받아서, 각각의 height와 overflow를 다르게 준다.

닫혀있을 땐 height를 보여주고 싶은 높이만큼 설정, overflow hidden,
열려있을 땐 height를 auto로 하여 모두 보여주게 하고, overflow는 auto.

export const ImageWrapper = styled(FlexColumnBox)<{ isOpen: boolean }>`
  width: 100%;
  min-width: 320px;
  max-width: 1000px;
  position: relative;
  margin-bottom: 50px;
  ${(props) =>
    props.isShown
      ? css`
          height: 100%;
          overflow-y: auto;
        `
      : css`
          height: 600px;
          overflow-y: hidden;
        `};
`;

export const OpenButton = styled.button`
  background-color: white;
  color: var(--grey900);
  border-radius: 4px;
  border: 1px solid var(--grey900);
  padding: 16px 0px;
  z-index: 4;
  bottom: 0px;
  position: absolute;
  width: 100%;
  font-weight: 600;
  font-size: 15px;
  justify-content: center;
  align-items: center;
`;

추가적인 CSS효과로 overlay를 주었는데 이미지 아래에 버튼이 바로 위치하게 되면 뚝 끊긴 느낌을 줄 수 있어, 그라데이션 overlay를 주어 자연스럽게 연결되도록 하였다.

export const OverLay = styled(FlexBox)`
  height: 100%;
  align-items: center;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  justify-content: center;
  background: linear-gradient(
    rgba(255, 255, 255, 0),
    rgba(255, 255, 255, 0.1),
    rgb(255, 255, 255)
  );
  z-index: 3;
`;

코드 상으로는 간단한 내용이지만, 상세 페이지 등에 자주 사용되는 UX/UI 이기 때문에 신경써서 만들어 보는 것이 좋다고 생각한다.

profile
안녕하세요 지원입니다.
post-custom-banner

0개의 댓글