Conversation
Walkthrough로그인용 UI 컴포넌트(Button, SNSLoginButton, TextField)와 관련 스토리들을 추가하고 로그인 페이지를 단순화했으며, 회원가입 페이지(RegisterPage) 및 해당 스토리북을 새로 추가했습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User
participant LoginPage
participant Button
participant SNSLoginButton
participant TextField
User->>LoginPage: 페이지 조회
Note right of LoginPage: 렌더링된 컴포넌트들
LoginPage->>TextField: 이메일/비밀번호 입력 컴포넌트 표시
LoginPage->>SNSLoginButton: SNS 로그인 버튼 표시
LoginPage->>Button: 일반 로그인 버튼 표시
User->>TextField: 입력 (onChange)
TextField-->>User: validation / focus handling
User->>SNSLoginButton: SNS 버튼 클릭
SNSLoginButton-->>User: (provider-specific action / icon shown)
User->>Button: 클릭
Button-->>User: onClick 호출 (비활성화 상태 처리)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (3)
apps/web/src/views/login/index.tsx (1)
3-17: 플레이스홀더 구현을 확인했습니다.현재 LoginPage는 단순한 텍스트만 렌더링하는 플레이스홀더입니다. 새로 추가된 컴포넌트(SNSLoginButton, TextField, Button)를 활용하여 실제 로그인 UI를 구성해야 합니다.
실제 로그인 화면 레이아웃 구현을 위한 코드를 생성해드릴까요?
apps/web/src/views/login/components/SNSLoginButton.tsx (1)
5-46: 인라인 스타일 대신 CSS-in-JS 또는 CSS 모듈 사용을 권장합니다.현재 모든 스타일이 인라인으로 작성되어 있어 유지보수가 어렵고 재사용성이 떨어집니다. styled-components, emotion, 또는 CSS 모듈을 활용하면 스타일 관리가 용이해집니다.
apps/web/src/views/login/components/TextField.tsx (1)
45-106: 인라인 스타일 대신 CSS-in-JS 또는 CSS 모듈 사용을 권장합니다.모든 스타일이 인라인으로 작성되어 있어 컴포넌트의 가독성과 유지보수성이 떨어집니다. styled-components나 CSS 모듈로 리팩토링하는 것을 권장합니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
apps/web/public/icons/google.svgis excluded by!**/*.svgapps/web/public/icons/kakao.svgis excluded by!**/*.svg
📒 Files selected for processing (5)
apps/web/src/views/login/components/Button.tsx(1 hunks)apps/web/src/views/login/components/SNSLoginButton.tsx(1 hunks)apps/web/src/views/login/components/TextField.tsx(1 hunks)apps/web/src/views/login/index.tsx(1 hunks)apps/web/src/views/login/login.stories.tsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/src/views/login/components/Button.tsx (1)
apps/web/src/shared/components/Button.tsx (1)
ButtonProps(3-14)
apps/web/src/views/login/login.stories.tsx (4)
apps/web/src/views/login/index.tsx (1)
LoginPage(3-17)apps/web/src/views/login/components/SNSLoginButton.tsx (1)
SNSLoginButton(5-48)apps/web/src/views/login/components/TextField.tsx (1)
TextField(20-107)apps/web/src/views/login/components/Button.tsx (1)
Button(9-33)
🔇 Additional comments (4)
apps/web/src/views/login/login.stories.tsx (3)
22-39: SNS 로그인 버튼 스토리가 클릭 동작을 보여주지 않습니다.현재 스토리는 버튼의 시각적 표현만 보여줍니다. SNSLoginButton 컴포넌트에 onClick 핸들러가 추가되면, 스토리에서도 클릭 이벤트를 처리하는 예제를 추가하는 것이 좋습니다.
SNSLoginButton에 onClick prop이 추가되면 다음과 같이 스토리를 업데이트하세요:
export const 구글_로그인: Story = { args: {}, render: () => ( <div style={{ width: "360px" }}> <SNSLoginButton provider="google" onClick={() => console.log("Google login clicked")} /> </div> ), };
56-61: 유효성 검사가 빈 값을 항상 허용합니다.이메일과 비밀번호 스토리의 validate 함수가 빈 값(value.length === 0)에 대해 true를 반환하므로, 필수 입력 필드 검증을 보여주지 못합니다. 스토리북 데모 목적으로는 적절할 수 있지만, 실제 로그인 폼에서는 필수 필드 검증이 필요합니다.
실제 로그인 폼 구현 시 required 필드 검증을 추가했는지 확인하세요.
Also applies to: 82-86
1-102: 스토리북 커버리지가 우수합니다.모든 주요 컴포넌트(SNSLoginButton, TextField, Button)에 대한 스토리가 잘 작성되어 있으며, 다양한 상태(활성/비활성, 에러, 유효성 검사)를 보여줍니다. 인터랙티브한 예제를 위해 React.useState를 적절히 활용했습니다.
apps/web/src/views/login/components/SNSLoginButton.tsx (1)
22-36: border 속성이 적용되지 않습니다.style 객체에
border속성이 정의되어 있지만, 실제 button 요소에는 기본 border 스타일을 제거하는 속성이 없어 variants의 border 설정이 제대로 적용되지 않을 수 있습니다.다음 diff를 적용하여 border 스타일을 수정하세요:
<button type="button" style={{ background: variants[provider].bg, color: variants[provider].color, border: variants[provider].border, + outline: "none", borderRadius: "5px",Likely an incorrect or invalid review comment.
| <button | ||
| type="button" | ||
| style={{ | ||
| backgroundColor: disabled ? "#B7B7B7" : "#3A8DFF", | ||
| color: "white", | ||
| borderRadius: "5px", | ||
| height: "50px", | ||
| display: "flex", | ||
| alignItems: "center", | ||
| justifyContent: "center", | ||
| cursor: disabled ? "not-allowed" : "pointer", | ||
| position: "relative", | ||
| width: "100%", | ||
| ...style, | ||
| }} |
There was a problem hiding this comment.
border와 outline 속성을 추가하세요.
button 요소의 기본 border를 제거하지 않으면 브라우저마다 다른 스타일이 적용될 수 있습니다.
다음 diff를 적용하세요:
style={{
backgroundColor: disabled ? "#B7B7B7" : "#3A8DFF",
color: "white",
+ border: "none",
+ outline: "none",
borderRadius: "5px",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <button | |
| type="button" | |
| style={{ | |
| backgroundColor: disabled ? "#B7B7B7" : "#3A8DFF", | |
| color: "white", | |
| borderRadius: "5px", | |
| height: "50px", | |
| display: "flex", | |
| alignItems: "center", | |
| justifyContent: "center", | |
| cursor: disabled ? "not-allowed" : "pointer", | |
| position: "relative", | |
| width: "100%", | |
| ...style, | |
| }} | |
| <button | |
| type="button" | |
| style={{ | |
| backgroundColor: disabled ? "#B7B7B7" : "#3A8DFF", | |
| color: "white", | |
| border: "none", | |
| outline: "none", | |
| borderRadius: "5px", | |
| height: "50px", | |
| display: "flex", | |
| alignItems: "center", | |
| justifyContent: "center", | |
| cursor: disabled ? "not-allowed" : "pointer", | |
| position: "relative", | |
| width: "100%", | |
| ...style, | |
| }} |
🤖 Prompt for AI Agents
In apps/web/src/views/login/components/Button.tsx around lines 11-25, the inline
style for the button is missing explicit border and outline properties; add
border: "none" and outline: "none" to the style object (keeping the existing
conditional and spread), ensuring the button removes browser-default borders and
outlines; if desired, also add a visible focus style separately for
accessibility instead of removing focus outlines entirely.
| <span | ||
| style={{ | ||
| color: "#E52929", | ||
| position: "absolute", | ||
| bottom: "-24px", | ||
| left: "0", | ||
| fontSize: "12px", | ||
| fontWeight: "500", | ||
| lineHeight: "140%", | ||
| letterSpacing: "-0.24px", | ||
| }} | ||
| > | ||
| {displayError} | ||
| </span> |
There was a problem hiding this comment.
에러 메시지 위치가 다른 요소와 겹칠 수 있습니다.
position: "absolute"와 bottom: "-24px"를 사용하여 에러 메시지를 배치하면, TextField 하단에 다른 요소가 있을 경우 겹쳐 보일 수 있습니다. 부모 컴포넌트에서 적절한 간격을 확보해야 합니다.
다음 중 하나를 고려하세요:
- 부모 div에
margin-bottom또는padding-bottom을 추가하여 공간 확보 - 에러 메시지를 문서 흐름 내에 배치(position: static)하여 자동으로 공간 확보
🤖 Prompt for AI Agents
In apps/web/src/views/login/components/TextField.tsx around lines 91 to 104, the
error message is absolutely positioned (position: "absolute", bottom: "-24px")
which can overlap adjacent elements; change the layout so the error does not
overlap by either (a) moving the error span into the document flow (remove
position/bottom and use default/static positioning) so it pushes content and
reserves space, or (b) keep absolute positioning but add appropriate bottom
spacing on the parent container (increase parent padding-bottom or margin-bottom
by at least 24px) and ensure the parent is positioned (relative) so the absolute
positioning is scoped; pick one approach and update styles accordingly.
There was a problem hiding this comment.
Actionable comments posted: 3
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/src/views/login/login.stories.tsx(1 hunks)apps/web/src/views/register/index.tsx(1 hunks)apps/web/src/views/register/register.stories.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/src/views/login/login.stories.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
apps/web/src/views/register/register.stories.tsx (2)
apps/web/src/views/register/index.tsx (1)
RegisterPage(3-17)apps/web/src/views/login/components/TextField.tsx (1)
TextField(20-107)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy Storybook to Chromatic
🔇 Additional comments (3)
apps/web/src/views/register/index.tsx (1)
1-17: 플레이스홀더 구현 확인됨.회원가입 페이지의 기본 스캐폴드가 정상적으로 구현되었습니다. 향후 실제 회원가입 폼과 로직을 추가할 때 인라인 스타일을 적절한 스타일링 솔루션으로 리팩토링하는 것을 권장합니다.
apps/web/src/views/register/register.stories.tsx (2)
6-14: Storybook 메타 설정이 올바릅니다.스토리북 설정이 표준 구조를 따르고 있으며 적절하게 구성되었습니다.
19-44: 이메일 입력 스토리가 정상적으로 구현되었습니다.이메일 유효성 검사 로직이 올바르게 작동하며, 빈 값과 유효한 이메일 형식을 적절히 처리하고 있습니다.
widse
left a comment
There was a problem hiding this comment.
@seungdeok
논의) texfiled의 error 위치
현재 TextField Component의 기준이 되는 디자인을 확인해보면 아래에 에러가 있는 형태인데요, 여기서는 Dynamic 방식으로 위치를 잡는건 어떨까요? 이슈 사항으로는 언급하셨던 "아래 요소들이 밀릴 수 있다" 가 있지만, 디자인시 이부분은 디자이너와의 협의로 "error가 나타날수 있는 ui이므로 해당 사항을 고려하여 영역을 잡아주세요" 와 같이 이루어질수 있을거 같습니다! Absolute, Fixed로 하게 될 경우 반대로 바로 아래 다른 ui가 있지만 겹치게 되는 상황이 생길 수 도 있고 ui 작업시 저한테는 Dynamic 방식이 조금더 직관적이였던 방법 같아요 :)
@widse
|
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (4)
apps/web/src/views/login/components/Button.tsx (1)
1-33: 과거 리뷰 코멘트 확인 필요이전 리뷰에서 제기된 다음 사항들이 아직 해결되지 않았습니다:
apps/web/src/shared/components/Button.tsx에 이미 Button 컴포넌트가 존재하여 코드 중복 문제 발생border및outline속성 누락으로 브라우저 기본 스타일 문제 가능성apps/web/src/views/login/components/TextField.tsx (1)
1-107: 과거 리뷰 코멘트 확인 필요이전 리뷰에서 제기된 다음 사항들이 아직 해결되지 않았습니다:
- 유효성 검사 로직 (lines 36-37): 빈 값 처리와 에러 메시지 표시 로직 개선 필요
- 불필요한 flex 속성 (lines 77-79): input 요소에
display: "flex",flexDirection,alignItems제거 필요- 에러 메시지 위치 (lines 91-104): absolute positioning으로 인한 요소 겹침 문제
PR 논의사항에서 Dynamic 방식으로 에러 위치를 처리하기로 결정했으나, 현재 코드는 absolute positioning을 사용하고 있습니다.
apps/web/src/views/register/register.stories.tsx (2)
46-84: 과거 리뷰 코멘트 확인 필요 - 중요 버그 포함이전 리뷰에서 제기된 다음 사항들이 아직 해결되지 않았습니다:
- 🔴 Critical - 비밀번호 확인 상태 관리 버그 (lines 67-80): 두 필드가 동일한
password상태를 사용하여 비밀번호 확인 기능이 작동하지 않습니다.- 비밀번호 검증 로직 불일치 (lines 61-65): 플레이스홀더는 "영대•소문자, 숫자, 특수문자 조합"을 요구하지만 길이만 검증합니다.
86-110: 과거 리뷰 코멘트 확인 필요이전 리뷰에서 제기된 닉네임 검증 로직 불일치 문제가 아직 해결되지 않았습니다:
- 검증 로직 불일치 (lines 101-105): 플레이스홀더는 "6~10자리 한글,숫자 조합"을 요구하지만 최소 길이만 검증합니다.
🧹 Nitpick comments (1)
apps/web/src/views/login/login.stories.tsx (1)
68-92: 검증 로직이 플레이스홀더 요구사항과 불일치함현재 검증은 길이(8-16자)만 확인하지만, 플레이스홀더는 "영대•소문자, 숫자, 특수문자 조합"을 명시하고 있습니다. Storybook 스토리이므로 실제 로그인 로직과 분리되어 있지만, 일관성을 위해 검증 로직이 플레이스홀더 설명과 일치하도록 개선하는 것을 권장합니다.
참고로
apps/web/src/views/register/register.stories.tsx의 비밀번호 스토리도 동일한 문제가 있습니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
apps/web/public/icons/google.svgis excluded by!**/*.svgapps/web/public/icons/kakao.svgis excluded by!**/*.svg
📒 Files selected for processing (7)
apps/web/src/views/login/components/Button.tsx(1 hunks)apps/web/src/views/login/components/SNSLoginButton.tsx(1 hunks)apps/web/src/views/login/components/TextField.tsx(1 hunks)apps/web/src/views/login/index.tsx(1 hunks)apps/web/src/views/login/login.stories.tsx(1 hunks)apps/web/src/views/register/index.tsx(1 hunks)apps/web/src/views/register/register.stories.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/web/src/views/login/index.tsx
- apps/web/src/views/login/components/SNSLoginButton.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
apps/web/src/views/login/components/Button.tsx (1)
apps/web/src/shared/components/Button.tsx (1)
ButtonProps(3-14)
apps/web/src/views/login/login.stories.tsx (3)
apps/web/src/views/login/index.tsx (1)
LoginPage(3-17)apps/web/src/views/login/components/SNSLoginButton.tsx (1)
SNSLoginButton(5-48)apps/web/src/views/login/components/TextField.tsx (1)
TextField(20-107)
apps/web/src/views/register/register.stories.tsx (2)
apps/web/src/views/register/index.tsx (1)
RegisterPage(3-17)apps/web/src/views/login/components/TextField.tsx (1)
TextField(20-107)
🔇 Additional comments (6)
apps/web/src/views/register/index.tsx (1)
1-17: LGTM! 향후 구현 필요현재는 "Register" 텍스트만 표시하는 플레이스홀더 컴포넌트입니다. Storybook 스토리에서 사용되는 TextField 컴포넌트들이 실제 RegisterPage에 통합될 예정인 것으로 보입니다.
apps/web/src/views/register/register.stories.tsx (1)
19-44: LGTM! 이메일 유효성 검사 적절함빈 값 허용과 유효한 이메일 형식 검증이 적절히 구현되어 있습니다.
apps/web/src/views/login/login.stories.tsx (4)
1-19: LGTM! Storybook 설정 적절함메타 설정과 임포트가 올바르게 구성되어 있습니다.
21-39: LGTM! SNS 로그인 버튼 스토리 구성 적절함구글과 카카오 로그인 버튼이 일관된 컨테이너 크기로 잘 구성되어 있습니다.
41-66: LGTM! 이메일 입력 스토리 적절함이메일 유효성 검사가 올바르게 구현되어 있으며, 빈 값 처리도 적절합니다.
94-103: LGTM! 로그인 버튼 스토리 적절함활성화 및 비활성화 상태의 버튼이 명확하게 표시되어 있습니다.
📝 PR 유형
📝 PR 설명
로그인 페이지의 주요 컴포넌트 개발을 진행합니다.
관련된 이슈 넘버
close #74
✅ 작업 목록
MR하기 전에 확인해주세요
📚 논의사항
📚 ETC
Summary by CodeRabbit