Language/Javascript

[styled Component] Styled Component로 custom dropdown 만들기

코찔이_suj 2022. 4. 11. 03:44
728x90

개요

오늘도 즐거운 팀프로젝트 기간... 휴학 1년과 이번 한달간 배운게 비등비등한 수준으로 팀에 적응하기 위해 열심히 살고있습니다... 

 

이번 포스트에서 다룰 내용은 styled Component를 이용해 custom component를 만드는 방법입니다.

Storybook을 하면서 styled component로 드롭다운을 만드는 업무를 하게 되었습니다. 처음에는 스타일에 custom이 그냥 select와 option으로 하면 금방 끝날 것 같았는데...  역시 오늘도 새벽이네요... 이번 중간고사는 3일 벼락치기만 해도 감사할 정도로 시간이 없어요.... ㅠㅠㅠㅠㅠㅠㅠㅠㅠ

 

그래서 이번 포스트는 scrollbar를 꾸민 법만 간단히만 적을거고 자세한건 나중에 올라올 저의 팀프젝 github의 src/components/Dropdown를 보면 될것 같습니다...

https://github.com/Kimsj912/GrooteogiFront

 

GitHub - Kimsj912/GrooteogiFront: [Web] 4학년 팀프로젝트 그루터기 frontend 레포짓토리

[Web] 4학년 팀프로젝트 그루터기 frontend 레포짓토리. Contribute to Kimsj912/GrooteogiFront development by creating an account on GitHub.

github.com

 

storybook 시작한지 2주차... 팀원들의 PR과 예시로 하나하나 배워가는 중입니다..... 얼렁 적고 잘게요....

 

 

 

본론

제가 선택한 방법은 div, button, ul, li 총 4개의 styled component를 만들어 custom을 하는 겁니다!

미리보는 결과물...

 

index.tsx

Dropdown의 구조는 대략 이렇게 구성되어있습니다.

const Dropdown = ({ list }: DropdownProps) => {
  const [acitve, setActive] = useState(true); // 리스트가 열려있는지 확인
  const [selected, setSelected] = useState(list[0]); // 선택된 값을 selected에 담아 컴포넌트 간에 공유
  return (
    <StyledSelectbox> // StyledSelectbox = button, ul을 담는 전체 div
      <StyledSelectedLabel value={selected} onClick={() => setActive(!acitve)}> // 선택된 값이 보여질 버튼
        {selected}
      </StyledSelectedLabel>
      <StyledOptionList active={acitve}> // 리스트를 보여줄 ul (ul을 열고 닫는 방식을 통해 드롭다운 구현)
        {list
          .filter(element => element !== selected) // 현재 selected된 값을 제외하고 보여주도록 함.
          .map(element => (
            <StyledOptionItem 
              key={element} // map을 쓰기 위해서는 해당 방식으로 key가 주어져야함.
              onClick={() => { // 클릭되면 active를 끄고 element로 선택된 값을 변경함.
                setActive(false);
                setSelected(element);
              }}
            > // li에 들어갈 리스트들
              {element}
            </StyledOptionItem>
          ))}
      </StyledOptionList>
    </StyledSelectbox>
  );
};

 

style.ts

총 4개의 styled component가 있기 때문에 가장 내부에 있는 li부터 바깥의 div로 나가는 방향으로 적어볼까해요.

Li (StyledOptionItem)

export const StyledOptionItem = styled.li`
  box-sizing: border-box;
  padding: 0.8rem 1rem 0.8rem 1rem;
  transition: 0.3s;
  &:hover {
    background: ${darken(0.1, '#ffffff')};
  }
`;

border-sizing -> li의 크기를 테두리를 기준으로 정하겠다.

padding -> li들간의 간격을 주기 위해 사용합니다.

transition와 &:hover -> hover되었을때 transition에 부과된 0.3s만큼 배경색인 하얀색에서 어두운 효과를 줍니다.

 

ul(StyledOptionList)

// max-height를 통해 드롭다운이 열렸을 때 보이는 길이와 닫혔을때 안보이는 효과를 준다.
const activeExist = ({ active = true }) => {
  return `max-height: ${active ? '300px' : '0'}`;
};

export const StyledOptionList = styled.ul`
  box-sizing: border-box; // 테두리에 맞게 ul 크기 조절
  position: absolute; // absolute를 이용해 위치를 원하는 곳에 둘것.
  top: 2.6rem; // 그곳에 위에서부터 2.6rem(드롭다운본체의 크기)만큼 떨어진 곳.
  list-style-type: none; // ul을 커스텀할 거라면 꼭 해줘야하는 list-style-type:none
  width: 100%; // 크기는 드롭다운 본체의 너비와 동일하게함.
  border-radius: 8px; // 동글동글하게 아래부분을 만들어야해서 border-radius를 줌.
  background: #ffffff; // 배경색
  ${activeExist}; 
  transition: 0.2s ease-in-out; // 0.2초를 걸려서 부드럽게 ul이 보이고 사라진다.
  overflow-y: scroll; // scroll을 통해 리스트 내용들을 보겠다.
  &::-webkit-scrollbar { // scrollbar 자체의 설정
  	// 너비를 작게 설정
    width: 6px; 
  }
  &::-webkit-scrollbar-track { // scrollbar의 배경부분 설정
  	// 부모와 동일하게 함(나중에 절전모드, 밤모드 추가되면 수정하기 번거로우니까... 미리 보이는 노동은 최소화)
    background: transparent;
  }
  &::-webkit-scrollbar-thumb { // scrollbar의 bar 부분 설정
  	// 동글동글한 회색 바를 만든다.
    border-radius: 1rem;
    background: ${darken(0.1, 'transparent')};
  }
  &::-webkit-scrollbar-button { // scrollbar의 상하단 위/아래 이동 버튼
  	// 크기를 안줘서 안보이게 함.
    width: 0;
    height: 0;
  }
`;

top과 width로 원래 dropdown박스의 크기만큼의 간격을 두며 하위로 보일 li들의 크기를 설정해줍니다.

원래 dropdown박스!

그리고 activeExist로 active가 true일 경우 max-height에 값을 주어 보이게 하고, active가 false일 경우 max-height를 0으로 줘 안보이게 합니다.

왼쪽 하단이 동글동글하죠!

그리고 border-radius를 줘서 전체적으로 동글동글하게 만들어주고!

 

overflow-y에 scroll을 줘서 값이 많아지면 scroll로 처리를 할 수 있도록 바꿔주고 각종 scrollbar에 관한 셋팅을 해줍니다.

 

button (StyledSelectedLabel)

export const StyledSelectedLabel = styled.button`
  // display설정
  display: flex; 
  align-items: center;
  border: none;
  // 크기 설정
  box-sizing: border-box; 
  width: inherit;
  height: inherit;
  // more 아이콘과 가까운 위치에 글자를 두기 위함.
  justify-content: right;
  padding-right: 2.5rem;
  // 글자 크기 설정
  font-size: 1rem;
  // more아이콘 설정
  background: url('/icons/expand_more.png') calc(100% - 0.5rem) center no-repeat;
  background-size: 2rem;
  // 커서가 올라오면 pointer모양으로 변경
  cursor: pointer;
`;

 

div (StyledSelectbox)

export const StyledSelectbox = styled.div`
  position: relative;
  width: 8rem;
  height: 2.6rem;
  border-radius: 8px;
  background: #ffffff;
  cursor: pointer;
`;

여기서는 딱 보이는 이 드롭다운 부분의 설정이 이뤄집니다.

div와 button부분이 합쳐져서 예쁜 디자인이 완성되는 것 같습니다...!

이부분!

 

마무리

벌써 4시가 다되어가네요... 어서 PR올리고 자러갈게요... 굿밤...!

 

Reference -> 도움을 많이 받은 페이지

https://wazacs.tistory.com/34

 

select 태그 커스텀 하기, 혹은 직접 만들기 (feat. javascript)

1. Select CSS Customizing Select 태그의 외형은 주로 각 브라우저에서 정의 합니다. 보다 시피 크롬(왼쪽), IE(오른쪽) 이 똑같이 보이면서도 미세 하게 다름니다. 공통적으로 둘 다 그리 예쁘게 생기진

wazacs.tistory.com

https://webisfree.com/2019-01-08/css-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%8A%A4%ED%81%AC%EB%A1%A4%EB%B0%94-%EC%8A%A4%ED%83%80%EC%9D%BC-%EC%A7%80%EC%A0%95-%EB%B0%94%EA%BE%B8%EB%8A%94-%EB%B0%A9%EB%B2%95-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

 

css 브라우저 스크롤바 스타일 지정, 바꾸는 방법 알아보기

css를 사용하여 브라우저 스크롤바의 스타일을 변경하는 방법에 대하여 알아봅니다. 커스텀 스크롤바라고도 부릅니다.

webisfree.com