-
Notifications
You must be signed in to change notification settings - Fork 2
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
[FE] feat: 사용자 프로필 정보 및 프로필 탭 구현 #1035
Conversation
frontend/src/styles/theme.ts
Outdated
dropdown: 997, | ||
profileTab: 998, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로필 탭은 모달 이외의 다른 모든 요소보다는 위에 떠야 하기 때문에 z-index 값을 조정했습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ProfileTab이 아닌 Topbar에 z-index를 설정했습니다!
|
||
export type ProfileTabElementType = 'readonly' | 'action' | 'divider'; | ||
|
||
export interface ProfileTabElement { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
주석 👍
content: socialType === 'github' && ( | ||
<div style={{ display: 'flex', gap: '1rem' }}> | ||
<img src={GitHubIcon} alt="소셜 아이콘" /> | ||
<span>GitHub 계정</span> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
content 부분의 레이아웃이 반복되고, 태그나 속성을 사용할 때 VS code 편의 기능이나, eslint, prettier 도움을 받지 못할 것 같아 불편할 것 같아요.
제안 1. content 를 리터럴 객체로 변경
content :{
icon : { src:GithubIcon, alt: '소셜 아이콘'},
text : 'Github 계정'}
제안2. 프로필 탭 요소 컴포넌트 재사용
프로필 탭 안의 요소들의 레이아웃이 동일하고 ,아이콘, 글자만 달라지니 컴포넌트를 만들어서 사용하는 방법
(클릭 이벤트는 이미 있어서 제외했지만, 클릭 이벤트를 props로 넣어줘도 괜찮겠네요)
const ContentLayout: = ({ icon, text }:ContnetLayoutProps) => (
<div style={{ display: 'flex', gap: '1rem' }}>
<img src={icon.src} alt={icon.alt} />
<span>{text}</span>
</div>
);
// 객체 배열
const profileTabElements= [
{
elementType: 'readonly',
isDisplayedOnlyMobile: true,
content: <ContentLayout icon={icon1} text={profileId} />,
},
{
elementType: 'editable',
isDisplayedOnlyMobile: false,
content: <ContentLayout iconSrc={icon2} text="다른 텍스트" />,
},
];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 합성 컴포넌트 스타일을 사용해서 TabItem에서 어떤 요소가 렌더링되는지 직관적으로 확인할 수 있는 방식을 제안해봅니다~
(사실 OptionSwitch를 리팩토링으로 생각해뒀던 방식입니다)
렌더링 요소가 실시간으로 변하거나 관리할 아이템들이 많아지면 배열이 좋겠지만 지금은 정적인 편이고 프로필 탭인 만큼 훗날 많은 요소가 추가될 것 같지는 않다는 생각입니다.
ProfileTab은 children을 렌더하는 컴포넌트로 사용하고, 각 아이템 요소들을 별도의 컴포넌트로 분리해서 최종적으로 아래와 같이 사용해보면 좋을 것 같아요.
<ProfileTab>
<ReadonlyItem>
<img src={src} alt="GitHub 로고" />
<span>GitHub 계정</span>
</ReadonlyItem>
....
컴포넌트를 분리한다면 바다가 제안해준대로 Content까지 분리해서 재활용하면 좋을 것 같네요!
</div> | ||
), | ||
}, | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
element에 id가 추가되면 좋을 것 같아요.
ProfileTab에서 key로 사용하면 좋고, profileTabElements 속 요소가 프로필 탭에서 어떤 부분인지 더 쉽게 눈에 띄었으면 좋겠어요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
에프이 프로필 관련 구현 잘 봤어요.
변수 이름에 깔끔해서 코드 읽기 쉬웠어요.
ProfileElement,zIndex 관련해 코멘트 남겨놨으니 확인 부탁해요.
새해복 많이 받아요!!
frontend/src/styles/theme.ts
Outdated
dropdown: 997, | ||
profileTab: 998, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
칼 같은 컨벤션으로 작성된 코드 잘 봤습니다~
건의사항을 남기긴 했지만ㅎㅎ 기존 코드와의 통일성을 지킨 코드 스타일이라는 게 느껴졌어요.
확실히 기존 드롭다운을 재사용하거나 확장하는 방법보다는 새로운 컴포넌트를 만들어 처리하는 게 더 나아 보입니다.
기존 컴포넌트를 재활용하거나 상속받는 스타일로 가려면 드롭다운과 프로필 탭을 아우르는, 더 추상화된 컴포넌트를 넣는 작업 등등을 해야 할 것 같은데 품이 많이 커질 것 같네요 😅
작업량을 떠나서 의미상으로도 괜찮아 보이고요!
그리고 github username으로 최대 39글자가 올 수 있다고 하는데, 37글자 영문으로 테스트해보니 800 이하 사이즈에서 프로필이 눌리고 있어요.
그리고 모바일 탭에서 id가 길어질 때 줄넘김 등으로 처리해야 할 것 같아요.
별개로 디자인 이야기지만, 상호작용 가능한 아이템과 그렇지 않은 아이템이 시각적으로 더 명확하게 구분되면 좋겠다는 생각이 들었어요.
저라면 처음에 Github 계정이나 아이디를 한번 클릭해볼 것 같아요. (비록 마우스를 갖다댔을 때 readonly 스타일로 작동하지만요)
꽤 까다로운 작업이었을 것 같은데 고생많았어요!
@@ -0,0 +1,10 @@ | |||
export type SocialType = 'github'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
로그인 버튼에서도 소셜 정보가 필요해서 아예 공통 타입으로 빼면 좋을 것 같아요! 로그인 도입 이후 다시 얘기해봐용
$isDisplayedOnlyMobile: boolean; | ||
} | ||
|
||
export const ProfileTabContainer = styled.div` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
탭 영역도 하나의 독립적 영역인 것 같아서 최상위 컨테이너는 section으로 하면 좋을 것 같아요!
return ( | ||
<S.ProfileTabContainer> | ||
<UndraggableWrapper> | ||
{items.map((item, index) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 map 함수를 별도의 함수로 분리(예: renderTabItem)해서 ProfileTab 컴포넌트의 리턴문을 간단하게 하는 건 어떤가요?
const ProfileTab = ({ items }: ProfileTabProps) => (
// switch 조건을 처리하는 render 함수는 별도로 선언
<S.ProfileTabContainer>
<UndraggableWrapper>
{items.map((item, index) => renderProfileTabItem(item, index))} // 함수를 사용해서 main 리턴문은 한 줄로 처리
</UndraggableWrapper>
</S.ProfileTabContainer>
);
switch문 내부가 복잡하지 않아서 지금 방식도 괜찮다고 생각하지만 에프이의 의견이 궁금해서요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
올리가 제안한 것처럼 return 문 내부는 짧게 만들고, render 함수를 따로 두는 편이 나을 것 같아요.
isDisplayedOnlyMobile: false, | ||
content: ( | ||
<div style={{ display: 'flex', gap: '1rem' }}> | ||
<img src={MenuIcon} alt="메뉴 아이콘" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로필 사진 UI는 관련 label 없이 사진만 있어서 alt 속성이 필수라고 생각했지만, 메뉴 아이콘들은 조금 고민이 되네요...
스크린 리더 사용자에게 시각 사용자와 같은 경험을 주기 위해서는 alt를 적극 활용해야 하지만 더 자세한 정보를 label로 읽을 수 있는데 아이콘의 의미를 설명하느라 중복 정보를 안내하는 게 아닌가 싶기도 해서요.
다른 팀원들의 생각도 궁금합니다~~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 장식용 아이콘의 경우, 스크린 리더기로 읽어주는 게 불필요하다고 생각해서 빈문자열을 선호합니다.(웹 접근성 미션 시, 스크린 리더기 사용 시, 불필요한 데이터까지 읽어주면 피로도가 올라가더라구요.)
올리 말대로 label로 읽을 수 있기애 빈문자열로 하는 편이 더 좋을 것 같아요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
옆에 텍스트가 함께 있기 때문에 아이콘 자체에는 큰 의미가 없을 것 같네요. 빈 문자열로 지정하는 것이 나을 듯해요 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
메뉴 아이콘이 없어도 리뷰 링크 관리
라는 텍스트가 이미 제공되고 있어서 탭 정보를 전달하는 데는 전혀 문제가 없다고 생각해요~ 오히려 너무 많은 정보를 전달하면 스크린 리더기 사용자 입장에서 더 불편할 수도 있을 것 같아요.. alt 속성을 빈 문자열로 처리하는 것에 한 표 하겠습니다~
content: socialType === 'github' && ( | ||
<div style={{ display: 'flex', gap: '1rem' }}> | ||
<img src={GitHubIcon} alt="소셜 아이콘" /> | ||
<span>GitHub 계정</span> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 합성 컴포넌트 스타일을 사용해서 TabItem에서 어떤 요소가 렌더링되는지 직관적으로 확인할 수 있는 방식을 제안해봅니다~
(사실 OptionSwitch를 리팩토링으로 생각해뒀던 방식입니다)
렌더링 요소가 실시간으로 변하거나 관리할 아이템들이 많아지면 배열이 좋겠지만 지금은 정적인 편이고 프로필 탭인 만큼 훗날 많은 요소가 추가될 것 같지는 않다는 생각입니다.
ProfileTab은 children을 렌더하는 컴포넌트로 사용하고, 각 아이템 요소들을 별도의 컴포넌트로 분리해서 최종적으로 아래와 같이 사용해보면 좋을 것 같아요.
<ProfileTab>
<ReadonlyItem>
<img src={src} alt="GitHub 로고" />
<span>GitHub 계정</span>
</ReadonlyItem>
....
컴포넌트를 분리한다면 바다가 제안해준대로 Content까지 분리해서 재활용하면 좋을 것 같네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export const ProfileImageWrapper = styled.div` | ||
overflow: hidden; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
|
||
width: 4rem; | ||
height: 4rem; | ||
|
||
background-color: ${({ theme }) => theme.colors.gray}; | ||
border-radius: 2rem; | ||
`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제가 리뷰 링크 관리 페이지 작업하면서 겸사겸사 헤더에 있는 리뷰미 로고 글자 크기를 2.8rem
으로 줄였어요! 지금 이미지 사이즈가 로고 사이즈보다 커서 이미지 사이즈도 그에 맞게 줄여야 할 것 같아요!
데스크탑 - width: 2.8rem
모바일 - width: 2.6rem
export const ProfileImageWrapper = styled.div`
// ...
width: 2.8rem;
height: 2.8rem;
${media.xSmall} {
width: 2.6rem;
height: 2.6rem;
}
`;
+추가로 border-radius: 50%로 줘도 둥글게 깎여요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
바뀐 크기 공유해주어서 고마워요 !! 작업할 때 함께 바꾸겠습니다
transform: ${({ $isOpened }) => ($isOpened ? 'rotate(180deg)' : 'rotate(0deg)')}; | ||
width: 2rem; | ||
height: 2rem; | ||
transition: transform 0.3s ease-in-out; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
센스 굳👍👍👍
isDisplayedOnlyMobile: false, | ||
content: ( | ||
<div style={{ display: 'flex', gap: '1rem' }}> | ||
<img src={MenuIcon} alt="메뉴 아이콘" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
메뉴 아이콘이 없어도 리뷰 링크 관리
라는 텍스트가 이미 제공되고 있어서 탭 정보를 전달하는 데는 전혀 문제가 없다고 생각해요~ 오히려 너무 많은 정보를 전달하면 스크린 리더기 사용자 입장에서 더 불편할 수도 있을 것 같아요.. alt 속성을 빈 문자열로 처리하는 것에 한 표 하겠습니다~
수정 사항프로필 탭의 최대 width 설정 (25rem)리팩토링
z-index 수정
readonly 타입의 element의 경우, 읽기 전용임을 구분할 수 있도록 했으면 좋겠다는 의견이 있었어요. 당장은 뾰족한 수가 생각나지 않아서 다음 회의에 다같이 이야기해봐도 좋을 것 같아요. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
변경사항 확인했어요. 저도 고정 width 말고 max-width를 주는 방식이 나은 것 같아요~
코드를 보다가 문득 useProfileTabElements
를 ProfileInfo
에서 호출해서 props로 ProfileTab
에 넘겨주는 방식을 선택한 이유가 있는지 궁금해졌어요.
useProfileTabElements
가 사실상 탭 컴포넌트에서만 쓰는, 역할 분리만을 위한 훅이라면 그냥 탭 내부에서 호출하는 게 책임 분리 측면에서 낫지 않을까 싶었습니다!
그렇게 중요한 부분은 아니라고 생각해서 어프루브는 지금 할게용 고생했어요!
useProfileTabElements 훅은 소셜 서비스와 유저 아이디 정보를 필요로 해요. ProfileInfo가 이 두 정보를 props로 받고 있는데, ProfileTab으로 한 번 더 props 전달하기보다는 ProfileTab이 elements 정보를 받게끔 했어요. 지금 다시 보니 ProfileInfo와 해당 훅은 연관이 없어서 ProfileTab에서 호출하는 방식이 더 좋을 것 같네요! 수정하겠습니다 :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
에프이~ 수정사항 확인 완료했습니다! 수고했어요👏
min-width: 100%; | ||
max-width: 25rem; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오오! 고정된 width가 아닌 max-width를 주는 게 훨씬 좋은 것 같아요👍👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정 사항 확인했습니다. 🚀
🚀 어떤 기능을 구현했나요 ?
🔥 어떻게 해결했나요 ?
프로필 정보
src
가 없이 오는 경우를 대비해서 기본적으로는 회색으로 보이게끔 했습니다.프로필 탭
768px 이하에서는 탭에 사용자의 ID가 보입니다.
Dropdown 컴포넌트의 재사용을 고려했으나 다음과 같은 이유로 별도의 컴포넌트로 구현했습니다.
클릭 불가능한 요소
,클릭 가능한 요소
,구분선
등이 올 수 있기 때문에 이 모든 것을 유연하게 처리하기 위해서는 새로운 컴포넌트를 만드는 것이 유리 (결정적인 이유)탭에 올 수 있는 각 요소들의 특성을
elementType
으로 구분해서 적절하게 처리하고, 변화에 유연하게 대처할 수 있게 했습니다.readonly
: 클릭 불가능한 요소입니다. 기본 커서가 적용되고, hover 효과 없으며 클릭 불가능합니다.action
: 클릭 가능한 요소입니다. pointer 커서가 적용되고, hover 효과가 있으며 클릭 이벤트를 등록할 수 있습니다.divider
: 프로필 탭 전용 구분선입니다.모바일에서만 보여지는 요소인지를
isDisplayedOnlyMobile
속성으로 구분합니다.▲ 데스크탑
▲ 모바일(768px 이하)
▲ 호버 시
useProfileTabElements
를 통해 프로필 탭에 들어가는 메뉴들과 클릭 이벤트 등을 관리합니다. 현재는 콘솔에 표시만 하고 있지만 추후에 각 페이지의 URL이 결정되면 동작을 수정할 계획입니다.📝 어떤 부분에 집중해서 리뷰해야 할까요?
📚 참고 자료, 할 말