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/slider Slider 컴포넌트 구현 #108

Merged
merged 31 commits into from
Apr 24, 2023
Merged

Feat/slider Slider 컴포넌트 구현 #108

merged 31 commits into from
Apr 24, 2023

Conversation

iyu88
Copy link
Member

@iyu88 iyu88 commented Apr 21, 2023

🤠 개요

💫 설명

  • 기존에 있던 RangeSelector(단일 Thumb 버전)에서 이름만 바뀌고 역할은 동일한 컴포넌트인 Slider 를 구현했습니다.

    • 추후 이중 Thumb를 가지고 있는 Slider는 RangeSlider 라는 이름으로 구현할 예정입니다.
  • 왜 단일부터 만들었냐면 RangeSelector의 구현 방식이 처음부터 안좋은 방식으로 되어 있던 것 같아서 그랬습니다.

    • 대표적으로 useLayoutEffect에서 DOM style 속성을 설정하여 초기 Filled (Slider에서 채워진 부분)와
      Thumb의 위치를 결정하는 로직입니다.
    • 또한 Thumb를 조절할 때 DOM의 위치와 value를 계산하는 로직을 일일히 짜다보니까 수식에 실수가 들어가기도 하고
      렌더링 오류로 직결되는 점이 걸렸습니다.
  • 새로운 컴포넌트라고 봐주시면 좋겠지만, 기존의 RangeSelector와 다른 점을 정리하면 다음과 같습니다.


  • Track 부분과 Thumb가 강결합되어 있던 점을 하위 컴포넌트 3가지 Track, Filled, Thumb 으로 분리했습니다.

    • Track : Thumb가 움직일 수 있는 범위입니다.
    • Filled : 현재 value만큼 Track이 채워지는 것을 표현하는 컴포넌트입니다.
    • Thumb : Slider의 컨트롤을 담당합니다.
  • useSlider 라는 커스텀 훅에 위치 계산 로직이나 스타일 관련 로직을 위치시켰습니다.

    • 앞에서 'Track 부분과 Thumb가 강결합되어 있다' 고 했는데 컴포넌트는 분리하고 계산 로직만 묶었다고 보시면 될 것 같습니다.
    • 결국 Track, Filled, Thumb는 긴밀하게 동작할 수 밖에 없기 때문에 계산 로직을 커스텀 훅에 담았고,
      동일한 이유로 함께 변경되는 CSS 스타일 객체도 훅 내부에 위치시켰습니다.
  • 앞서 설명드린 것처럼 위치 계산 방법을 변경했습니다.

    • position: absolute인 점을 이용하여 비율 (%) 를 계산해서 left 나 bottom 을 설정하기 때문에 위치 오류가 발생하지 않습니다.
      (특히, resize 시)
  • 방향 설정이 가능합니다 ( default 는 horizontal )

  • step 으로 한 번에 조절되는 value를 설정할 수 있습니다. ( default 는 1 )

  • 키보드 접근성에 디테일을 추가했습니다. 참고 링크 - 널리

    • ⬅️ ⬇️ : 값이 step만큼 감소합니다.
    • ➡️ ⬆️ : 값이 step만큼 증가합니다.
    • PageDown : 10% 감소합니다.
    • PageUp : 10% 증가합니다.
    • Home : 최소값이 됩니다.
    • End : 최대값이 됩니다.
  • FormData에서 값을 받아올 때를 대비해서 input 태그를 Thumb 내부에 위치시켰습니다.

  • 자세한 동작은 스토리북을 확인해주세요

📷 스크린샷 (Optional)

  • 키보드 이벤트 영상 첨부합니다.

방향키

2023-04-21.18.29.10.mov

PageDown / PageUp

2023-04-21.18.30.11.mov

Home / End

2023-04-21.18.29.54.mov

iyu88 added 24 commits April 19, 2023 17:12
id props은 삭제하고 label prop을 활용합니다.
방향을 결정하는 orientation prop을 추가합니다.
useContext를 추상화한 useSafeContext를 적용합니다.
position을 absolute로 설정하여 각 하위 컴포넌트의 위치를 적절하게 설정합니다.
마우스 이벤트를 실행했을 때 Thumb와 Filled를 적절하게 움직이기 위한 이벤트 핸들러를 분리합니다.
스타일 객체를 각 하위 컴포넌트에서 import 해서 사용하기 위해서 커스텀 훅 내부에 스타일을 가져올 수 있는 함수를 생성합니다.
Thumb의 위치와 Filled의 비율을 해당 함수에 바로 적용하기 위해서 각각을 저장하기 위한 state를 추가로 선언합니다.
기존에 있던 마우스 이벤트 핸들러 관련 함수들을 통폐합합니다.
최종적인 함수는 onMoveSlider 만 남겨서 마우스 이벤트를 핸들링합니다.
Slider로 컴포넌트 이름을 변경하고 useSlider 훅을 적용합니다.
기존에 잘못되었던 접근성 속성 사용법을 바로잡습니다.

https://nuli.navercorp.com/community/article/1132993
orientation에 따라 화살표 키로 값을 조절하는 방식이 달라졌던 점을 orientation과 무관하게 수정되도록 합니다.
추가적인 PageUp / PageDowm / Home / End 키에 이벤트를 추가합니다.

- PageDown : 10% 줄입니다.
- PageUp : 10% 높입니다.
- Home : 최소값으로 만듭니다.
- End : 최대값으로 만듭니다.

https://nuli.navercorp.com/community/article/1132993
https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/
FormData를 사용해서 Slider 값을 가져오게 될 경우에 대비하여 input 태그를 추가합니다.
display: none 으로 설정해서 렌더링에 방해되지 않도록 합니다.
@iyu88 iyu88 added the ✨ feat 기능 구현 label Apr 21, 2023
@iyu88 iyu88 self-assigned this Apr 21, 2023
Copy link
Contributor

@prayinforrain prayinforrain left a comment

Choose a reason for hiding this comment

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

멋있어요~ 처음 것보다 코드 읽기도 훨씬 수월해졌어요. 슬라이더 자체가 어려운 컴포넌트지만 ㅎㅎ..
몇가지 질문과 제안이 있어요.

  1. Track의 clickable 영역이 조금 더 넓었으면 해요.
    트랙은 보통 가느다란(?) 편이니까.. 적어도 Thumb가 차지하는 만큼의 높이(수직 슬라이더면 너비)는 가져가도 되지 않을까요? padding과 pointer-events를 잘 넣으면 될 것 같아요(추상적)
  2. 사용에 꼭 합성 컴포넌트가 필요할까요?
    제가 이해한 구조가 맞다면 color는 Slider 컴포넌트의 props로 받아서 내려줘도 될 것 같고, custom thumb도 Slider props에 추가해도 괜찮을 것 같아요. 뭔가 더 복잡한 커스터마이징 시나리오가 있다면 지금의 형태로 분리해서 사용하는 게 이득이겠지만 지금은 분리해서 구현되어 있더라도 사용자에게는 하나의 <Slider/> 형태로 합쳐서 제공해도 될 것 같아요. 다른 이유가 있을 수도 있겠지만요 ㅎㅎ..
  3. size를 100%로 주는 방법은 없을까요?
    기술적으로 어려움이 있을 수도 있겠지만 제가 만약 사용자라면 이게 가능한지를 찾아볼 것 같아요.
  4. step props의 단위는 px인가요 value인가요?
    withStep10 스토리를 보면 width가 200px이고, step이 10이고, value값은 0 ~ 100으로 보이는데, 설명에 의하면 step : 10은 10px씩 움직이니 value는 5단위로 조절되어야 할 것처럼 생각되지만 실제로는 10씩 움직여요.

그리고.. 드래그를 지나치게 빠르게 하면 value가 끝값까지 안오는 버그가 있네요. 이건 해결할 수 있는 문제인지는 잘 모르겠어요. 아니면 제 컴퓨터가 지금 아픈걸수도(?)

Copy link
Contributor

@leesunmin1231 leesunmin1231 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다~!! 위치 계산로직을 훅으로 따로 빼니까 훨씬 깔끔해요 ㅎㅎ
Thumb 안에 숫자는 확인용으로 넣어두신 건가요? default 스타일로 심플한 동그라미 하나 달아 놓으면 예쁠거 같아요

수정) 제것도 우재님이 말하신 것과 같은 버그가 있어요. value가 끝값까지 안오네요..

src/components/Slider/index.tsx Outdated Show resolved Hide resolved
src/components/Slider/useSlider.ts Outdated Show resolved Hide resolved
src/components/Slider/useSlider.ts Outdated Show resolved Hide resolved
src/components/Slider/useSlider.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@se030 se030 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! 계산 로직이 분리돼서 눈에 잘 들어왔어요 ㅎㅎ

저도 사용법 관련해서 하나 코멘트하면 사용처에서 Track, Filled, Thumb를 커스텀하고 싶지 않은 경우에는 하위 컴포넌트를 따로 작성하지 않아도 기본 스타일을 제공할 수 있으면 좋겠어요 ~ Slider에서 children 여부로 판단이 가능할 것 같아요.

src/components/Slider/useSlider.ts Outdated Show resolved Hide resolved
src/components/Slider/useSlider.ts Outdated Show resolved Hide resolved
src/components/Slider/Slider.stories.tsx Show resolved Hide resolved
src/components/Slider/index.tsx Outdated Show resolved Hide resolved
size의 기본값을 100% 로 받도록 변경합니다.
props 중에서 optional로 받아도 되는 값을 type에 명시합니다.
변경된 props와 잘못된 설명을 수정합니다.
Slider 태그만 사용한 템플릿을 추가합니다.
filled와 track에서 사용하는 상태를 하나로 합칩니다.
onPressArrow의 코드 스타일을 switch문으로 변경합니다.
onMoveSlider의 이벤트 타입에 native 이벤트도 추가합니다.
마우스 이벤트를 마우스 위치가 아닌 계산된 value 값을 기준으로 제한합니다.
변경된 size prop을 하위 컴포넌트들의 스타일 객체에 반영합니다.
Show Code에 표시되는 내용을 깔끔하게 정리합니다.
하위 컴포넌트에 displayName을 부여합니다.
decorator에서 사용하는 컴포넌트의 스타일 정의 방식을 수정합니다.
Slider의 root에 있던 margin 값을 삭제합니다.
스토리 decorator에 padding을 추가합니다.
@iyu88 iyu88 merged commit 7ad1c10 into main Apr 24, 2023
@iyu88 iyu88 deleted the feat/slider branch April 24, 2023 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ feat 기능 구현
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants