Skip to content

[Feat/#79] feat(web): 로그인/회원가입 UI 컴포넌트 및 기능 구현#81

Open
seungdeok wants to merge 6 commits intomainfrom
feat/#79
Open

[Feat/#79] feat(web): 로그인/회원가입 UI 컴포넌트 및 기능 구현#81
seungdeok wants to merge 6 commits intomainfrom
feat/#79

Conversation

@seungdeok
Copy link
Member

@seungdeok seungdeok commented Oct 18, 2025

📝 PR 유형

  • 🚀 feature 기능 추가
  • 🐞 버그 발생
  • 🔨 리팩토링
  • 📋 문서작성
  • 🌍 빌드 설정 및 문제
  • ETC

📝 PR 설명

로그인 및 회원가입 페이지의 UI 컴포넌트와 관련 기능들을 구현했습니다.

관련된 이슈 넘버

✅ 작업 목록

  • 로그인 페이지 UI 컴포넌트 구현
  • 회원가입 페이지 UI 컴포넌트 구현
  • TextField 컴포넌트 리셋, 숨기기, 유효성검사 기능 추가
  • 회원가입 페이지 탑바 컴포넌트 추가
  • 로그인 페이지 아이디/비밀번호 찾기 및 회원가입 링크 추가
  • SNS 계정으로 로그인 기능 추가
  • 통합 에러 메시지 처리 기능 추가
  • Storybook 스토리 파일 추가
  • 필요한 아이콘 리소스 추가

MR하기 전에 확인해주세요

  • local code lint 검사를 진행하셨나요?
  • local ci test를 진행하셨나요?

📚 논의사항

  • 에러 메시지 표시 방식이 사용자 경험에 적합한지 검토 필요

📚 ETC

Summary by CodeRabbit

  • 새로운 기능

    • 텍스트 필드에 비밀번호 표시/숨김 토글과 입력 초기화 리셋 버튼 추가
    • 유효성 검사 결과를 아이콘으로 표시하는 상태 표시 기능 추가
    • 회원가입 흐름용 상단 네비게이션(TopBar) 컴포넌트 및 관련 스토리 추가
    • 로그인/회원가입 스토리에 링크, SNS 로그인 안내 및 다양한 예시 화면 추가
  • 사용자 경험 개선

    • 로그인 폼에 통합 오류 메시지 및 인라인 유효성 검사 강화

@coderabbitai
Copy link

coderabbitai bot commented Oct 18, 2025

Walkthrough

로그인 TextField에 비밀번호 가시성 토글, 유효성 상태 아이콘, 리셋 버튼 옵션이 추가되고, register 흐름용 TopBar 컴포넌트가 도입되었으며 관련 로그인/회원가입 스토리가 해당 기능으로 확장되었습니다.

Changes

Cohort / File(s) Summary
TextField 컴포넌트 개선
apps/web/src/views/login/components/TextField.tsx
useValidationStatus?: boolean, useResetButton?: boolean props 추가. 내부 password visibility 토글(isPasswordVisible), getInputType, togglePasswordVisibility 구현. 값 기반 유효성 성공/오류 계산 및 상태 아이콘(체크 활성/비활성), 리셋 버튼(값 초기화) UI 추가. 입력 래퍼 + 절대 위치 액션 그룹으로 구조 조정. 이미지 아이콘 import(Next.js Image) 추가.
로그인 스토리 확장
apps/web/src/views/login/login.stories.tsx
Link 사용 추가. 세 가지 신규 스토리 추가: 아이디/비밀번호/회원가입 링크 행, SNS 로그인 안내 분리선, 통합 에러 메세지 스토리(이메일 형식 및 비밀번호 길이 검증, 에러 블록, 로그인 버튼).
TopBar 컴포넌트 추가
apps/web/src/views/register/components/TopBar.tsx
TopBar 함수형 컴포넌트 추가: leftActions, title, rightActions, style, className props; 좌/우 액션을 절대 위치시키고 중앙 제목 렌더링.
회원가입 스토리 업데이트
apps/web/src/views/register/register.stories.tsx
TopBar 도입 스토리 추가. 이메일/비밀번호/닉네임 스토리에서 useValidationStatususeResetButton 사용(비밀번호 확인 로직 포함). next/image import 추가 및 레이아웃 조정.

Sequence Diagram

sequenceDiagram
    participant User
    participant TextField
    participant ParentState as State

    User->>TextField: 입력(value) 또는 아이콘 클릭
    TextField->>ParentState: onChange(value)
    ParentState-->>TextField: prop value 업데이트

    alt password field
        User->>TextField: 눈(토글) 클릭
        TextField->>TextField: togglePasswordVisibility()
        TextField-->>User: input type 변경("password" ↔ "text")
    end

    alt useValidationStatus && value 존재
        TextField->>TextField: hasValidationError / hasValidationSuccess 계산
        TextField-->>User: 검증 아이콘(활성/비활성) 표시
    end

    alt useResetButton && value 존재
        User->>TextField: 리셋 버튼 클릭
        TextField->>ParentState: onChange("")
        ParentState-->>TextField: value = ""
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • [Feat/#74] 인증 화면 개발 #76: 동일한 apps/web/src/views/login/components/TextField.tsx 파일과 TextField API를 변경하는 PR로 직접적인 코드 레벨 연관성이 있습니다.

Suggested labels

enhancement

Suggested reviewers

  • widse

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 "[Feat/#79] feat(web): 로그인/회원가입 UI 컴포넌트 및 기능 구현"는 변경사항의 핵심을 명확하게 요약하고 있습니다. raw_summary에 따르면 TextField 컴포넌트 기능 확장, TopBar 새 컴포넌트 추가, login 및 register 페이지의 스토리북 파일 수정 등이 포함되어 있으며, 제목은 이러한 로그인/회원가입 UI 구현 작업을 정확하게 반영하고 있습니다. 제목은 간결하면서도 개발자의 관점에서 주요 변경사항을 효과적으로 전달하고 있습니다.
Description Check ✅ Passed PR 설명이 제공된 템플릿의 대부분 필수 섹션을 충실히 포함하고 있습니다. PR 유형(feature), PR 설명, 작업 목록(9개 항목 모두 완료), MR 전 확인사항(lint 및 CI 테스트 완료), 논의사항(에러 메시지 표시 방식 검토)이 모두 작성되어 있습니다. 다만 "관련된 이슈 넘버" 섹션이 주석 처리된 상태이며, ETC 섹션이 비어있지만 전체적으로 충분한 정보를 제공하고 있습니다. 작업 목록이 구체적이고 명확하며, 검토자에게 필요한 배경 정보와 검토 포인트가 잘 제시되어 있습니다.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#79

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@seungdeok seungdeok changed the title feat(web): 로그인/회원가입 UI 컴포넌트 및 기능 구현 [Feat/#79] feat(web): 로그인/회원가입 UI 컴포넌트 및 기능 구현 Oct 18, 2025
@seungdeok seungdeok self-assigned this Oct 18, 2025
@seungdeok seungdeok requested a review from widse October 18, 2025 07:18
@seungdeok seungdeok marked this pull request as ready for review October 18, 2025 07:18
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (7)
apps/web/src/views/login/login.stories.tsx (1)

111-120: 통합 에러 메시지의 UX 개선을 고려하세요.

현재 구현은 하나의 에러 메시지만 표시하여 사용자가 어느 필드에 문제가 있는지 명확히 알기 어렵습니다. 예를 들어, 이메일과 비밀번호 모두 잘못된 경우 이메일 에러만 표시됩니다.

PR 논의사항에서 언급된 대로 에러 메시지 표시 방식 검토가 필요합니다. 다음 방식들을 고려해보세요:

  • 각 필드에 인라인 에러 표시 (TextField의 error prop 활용)
  • 여러 에러를 모두 나열
  • 필드 포커스를 통한 에러 안내
apps/web/src/views/register/components/TopBar.tsx (2)

40-42: 배열 인덱스를 키로 사용할 때 주의하세요.

현재 index를 키로 사용하고 있는데, 액션 배열의 순서가 변경되거나 항목이 추가/삭제될 경우 React의 재조정(reconciliation) 문제가 발생할 수 있습니다. 스토리북 용도로는 문제없지만, 실제 사용 시에는 각 액션에 고유한 식별자를 사용하는 것이 좋습니다.

또한 Line 41, 59에서 .toString()은 템플릿 리터럴이 자동으로 문자열 변환을 하므로 불필요합니다.

-          <Fragment key={`top-bar-left-action-${index.toString()}`}>{action}</Fragment>
+          <Fragment key={`top-bar-left-action-${index}`}>{action}</Fragment>

Also applies to: 58-60


11-64: 타이틀과 액션 간 오버플로우 처리를 고려하세요.

leftActionsrightActions가 절대 위치로 배치되어 있고, 타이틀은 width: "100%"로 중앙 정렬되어 있습니다. 액션이 많거나 타이틀이 긴 경우 시각적 겹침이 발생할 수 있습니다.

다음 개선을 고려해보세요:

  • 타이틀에 overflow: hidden, text-overflow: ellipsis 추가
  • 타이틀 영역에 좌우 패딩 추가하여 액션과의 최소 간격 확보
apps/web/src/views/register/register.stories.tsx (2)

153-153: 플레이스홀더 URL을 적절한 값으로 교체하세요.

모든 링크가 "https://google.com"을 가리키고 있습니다. 스토리북 시연 목적이라면 "#" 또는 실제 라우트 경로를 사용하는 것이 좋습니다.

-          href="https://google.com"
+          href="#"

Also applies to: 167-167, 181-181


139-188: 스토리 구성을 검토하세요.

아이디_찾기_비밀번호_찾기_회원가입SNS_계정으로_로그인 스토리는 회원가입 페이지보다는 공통 네비게이션/레이아웃 컴포넌트에 더 적합해 보입니다.

이러한 UI 요소들을 별도의 컴포넌트로 추출하고 해당 컴포넌트의 스토리 파일에서 문서화하는 것을 고려해보세요. 이렇게 하면 재사용성이 높아지고 스토리 구조가 더 명확해집니다.

Also applies to: 190-226

apps/web/src/views/login/components/TextField.tsx (2)

126-138: 버튼 스타일을 명시적으로 초기화하세요.

button 요소에 기본 브라우저 스타일이 적용될 수 있습니다. 일관된 렌더링을 위해 다음 스타일을 추가하세요:

                 style={{ cursor: "pointer" }}
+                style={{ 
+                  cursor: "pointer",
+                  border: "none",
+                  background: "none",
+                  padding: 0,
+                  display: "flex",
+                  alignItems: "center"
+                }}

Also applies to: 151-153


140-140: 일관성을 위해 currentValue 사용을 고려하세요.

Lines 140, 150에서 value를 직접 확인하고 있지만, 컴포넌트 내에서는 currentValue = value || ""로 정규화된 값을 사용하고 있습니다. 일관성을 위해 currentValue를 사용하거나, value가 빈 문자열일 수 있다면 명시적으로 체크하는 것이 좋습니다.

-            value && useValidationStatus && (
+            currentValue && useValidationStatus && (
-            value && useResetButton && (
+            currentValue && useResetButton && (

Also applies to: 150-150

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a36021a and 64c7521.

⛔ Files ignored due to path filters (5)
  • apps/web/public/icons/components/arrow-left-black.png is excluded by !**/*.png
  • apps/web/public/icons/components/check-active.png is excluded by !**/*.png
  • apps/web/public/icons/components/check-inactive.png is excluded by !**/*.png
  • apps/web/public/icons/components/eye.png is excluded by !**/*.png
  • apps/web/public/icons/components/reset.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • apps/web/src/views/login/components/TextField.tsx (5 hunks)
  • apps/web/src/views/login/login.stories.tsx (1 hunks)
  • apps/web/src/views/register/components/TopBar.tsx (1 hunks)
  • apps/web/src/views/register/register.stories.tsx (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/src/views/login/login.stories.tsx (2)
apps/web/src/views/login/components/TextField.tsx (1)
  • TextField (23-175)
apps/web/src/views/login/components/Button.tsx (1)
  • Button (9-33)
apps/web/src/views/register/register.stories.tsx (2)
apps/web/src/views/login/components/TextField.tsx (1)
  • TextField (23-175)
apps/web/src/views/register/components/TopBar.tsx (1)
  • TopBar (11-64)
🔇 Additional comments (3)
apps/web/src/views/login/login.stories.tsx (1)

124-148: TextField 컴포넌트에 에러 메시지가 전달되지 않습니다.

TextField는 error prop을 통해 인라인 에러 메시지를 표시할 수 있지만, 현재 이 스토리에서는 전달하지 않고 있습니다. 이로 인해 필드별 에러 표시 기능을 테스트할 수 없습니다.

통합 에러 메시지 방식을 유지하더라도, 필드별 에러 prop을 조건부로 전달하여 두 가지 패턴을 모두 시연할 수 있습니다.

apps/web/src/views/register/register.stories.tsx (1)

43-44: 필드 기능 향상이 잘 적용되었습니다.

useValidationStatususeResetButton 플래그를 추가하여 TextField의 새로운 기능을 스토리에서 시연하고 있습니다. 이는 컴포넌트의 다양한 사용 패턴을 문서화하는 좋은 방법입니다.

Also applies to: 72-72, 87-87, 114-115

apps/web/src/views/login/components/TextField.tsx (1)

43-45: 변수명이 의도를 명확히 전달합니다.

hasValidationErrorhasValidationSuccess는 서로 다른 조건을 확인합니다:

  • hasValidationError: 검증 실패 여부 (값이 있고 검증 함수가 false 반환)
  • hasValidationSuccess: 검증 성공 여부 (값이 있고 검증 함수가 true 반환)

빈 값일 때는 둘 다 false이므로 로직이 올바르게 동작합니다.

Comment on lines +124 to +155
{...[
type === "password" && (
<button
type="button"
onClick={togglePasswordVisibility}
aria-label={isPasswordVisible ? "비밀번호 숨기기" : "비밀번호 보기"}
style={{ cursor: "pointer" }}
>
<Image
src="/icons/components/eye.png"
alt={isPasswordVisible ? "비밀번호 숨기기" : "비밀번호 보기"}
width={20}
height={20}
/>
</button>
),
value && useValidationStatus && (
<Image
src={
hasValidationSuccess ? "/icons/components/check-active.png" : "/icons/components/check-inactive.png"
}
alt="유효성 검사 통과"
width={20}
height={20}
/>
),
value && useResetButton && (
<button type="button" onClick={() => onChange?.("")} aria-label="초기화" style={{ cursor: "pointer" }}>
<Image src="/icons/components/reset.png" alt="초기화" width={20} height={20} />
</button>
),
]}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

JSX 배열 렌더링 문법 오류를 수정하세요.

Line 124의 {...[...]} 구문은 올바른 React 문법이 아닙니다. 스프레드 연산자는 JSX 요소 배열을 렌더링하는 데 사용할 수 없습니다.

또한 type === "password" && 표현식은 조건이 거짓일 때 false를 반환하며, 이는 React에서 렌더링되지 않지만 혼란을 줄 수 있습니다.

다음과 같이 수정하세요:

         >
-          {...[
+          {[
             type === "password" && (
               <button
                 type="button"
                 onClick={togglePasswordVisibility}
                 aria-label={isPasswordVisible ? "비밀번호 숨기기" : "비밀번호 보기"}
                 style={{ cursor: "pointer" }}
               >
                 <Image
                   src="/icons/components/eye.png"
                   alt={isPasswordVisible ? "비밀번호 숨기기" : "비밀번호 보기"}
                   width={20}
                   height={20}
                 />
               </button>
             ),
             value && useValidationStatus && (
               <Image
                 src={
                   hasValidationSuccess ? "/icons/components/check-active.png" : "/icons/components/check-inactive.png"
                 }
                 alt="유효성 검사 통과"
                 width={20}
                 height={20}
               />
             ),
             value && useResetButton && (
               <button type="button" onClick={() => onChange?.("")} aria-label="초기화" style={{ cursor: "pointer" }}>
                 <Image src="/icons/components/reset.png" alt="초기화" width={20} height={20} />
               </button>
             ),
-          ]}
+          ].filter(Boolean)}
         </div>

filter(Boolean)을 추가하여 falsy 값을 제거하면 더 안전합니다.

📝 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.

Suggested change
{...[
type === "password" && (
<button
type="button"
onClick={togglePasswordVisibility}
aria-label={isPasswordVisible ? "비밀번호 숨기기" : "비밀번호 보기"}
style={{ cursor: "pointer" }}
>
<Image
src="/icons/components/eye.png"
alt={isPasswordVisible ? "비밀번호 숨기기" : "비밀번호 보기"}
width={20}
height={20}
/>
</button>
),
value && useValidationStatus && (
<Image
src={
hasValidationSuccess ? "/icons/components/check-active.png" : "/icons/components/check-inactive.png"
}
alt="유효성 검사 통과"
width={20}
height={20}
/>
),
value && useResetButton && (
<button type="button" onClick={() => onChange?.("")} aria-label="초기화" style={{ cursor: "pointer" }}>
<Image src="/icons/components/reset.png" alt="초기화" width={20} height={20} />
</button>
),
]}
{[
type === "password" && (
<button
type="button"
onClick={togglePasswordVisibility}
aria-label={isPasswordVisible ? "비밀번호 숨기기" : "비밀번호 보기"}
style={{ cursor: "pointer" }}
>
<Image
src="/icons/components/eye.png"
alt={isPasswordVisible ? "비밀번호 숨기기" : "비밀번호 보기"}
width={20}
height={20}
/>
</button>
),
value && useValidationStatus && (
<Image
src={
hasValidationSuccess ? "/icons/components/check-active.png" : "/icons/components/check-inactive.png"
}
alt="유효성 검사 통과"
width={20}
height={20}
/>
),
value && useResetButton && (
<button type="button" onClick={() => onChange?.("")} aria-label="초기화" style={{ cursor: "pointer" }}>
<Image src="/icons/components/reset.png" alt="초기화" width={20} height={20} />
</button>
),
].filter(Boolean)}
🤖 Prompt for AI Agents
In apps/web/src/views/login/components/TextField.tsx around lines 124-155, the
JSX currently uses an invalid `{...[ ... ]}` spread of an array which is not
valid React syntax and can produce falsy values (false) in the output; replace
the spread-within-braces approach by returning the elements directly (e.g., wrap
them in a fragment or return the array expression itself) and filter out falsy
values with `.filter(Boolean)` before rendering so conditional `&&` expressions
don't leave false in the render tree; also ensure each array item has a stable
key when rendering an array of elements.

@seungdeok
Copy link
Member Author

seungdeok commented Oct 18, 2025

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
apps/web/src/views/login/login.stories.tsx (2)

195-195: 스토리 이름의 오타 수정 필요

"통합_에러_메세지"는 "통합_에러_메시지"로 수정해야 합니다 (메세지 → 메시지).

-export const 통합_에러_메세지: Story = {
+export const 통합_에러_메시지: Story = {

207-207: 한국어 텍스트 띄어쓰기 오류

"잘못된 비밀번호 입니다."는 "잘못된 비밀번호입니다."로 수정해야 합니다 (입니다 앞 공백 제거).

-      if (password.length < 8 || password.length > 16) return "잘못된 비밀번호 입니다.";
+      if (password.length < 8 || password.length > 16) return "잘못된 비밀번호입니다.";
🧹 Nitpick comments (2)
apps/web/src/views/login/login.stories.tsx (2)

106-155: 인라인 스타일 중복 및 플레이스홀더 URL

세 개의 Link 컴포넌트가 동일한 스타일 객체를 중복하여 사용하고 있으며, 모든 링크가 플레이스홀더 URL(https://google.com)을 가리키고 있습니다.

스타일 객체를 상수로 추출하여 중복을 제거하는 것을 권장합니다:

 export const 아이디_찾기_비밀번호_찾기_회원가입: Story = {
   args: {},
   render: () => {
+    const linkStyle = {
+      color: "#111",
+      fontSize: "12px",
+      fontStyle: "normal",
+      fontWeight: "500",
+      lineHeight: "140%",
+      letterSpacing: "-0.24px",
+    };
+
     return (
       <div style={{ width: "360px", display: "flex", flexDirection: "row", gap: "10px", alignItems: "center" }}>
         <Link
-          style={{
-            color: "#111",
-            fontSize: "12px",
-            fontStyle: "normal",
-            fontWeight: "500",
-            lineHeight: "140%",
-            letterSpacing: "-0.24px",
-          }}
+          style={linkStyle}
           href="https://google.com"
         >
           아이디 찾기
         </Link>
         <div style={{ width: "1px", height: "11px", backgroundColor: "#D9D9D9" }} />
         <Link
-          style={{
-            color: "#111",
-            fontSize: "12px",
-            fontStyle: "normal",
-            fontWeight: "500",
-            lineHeight: "140%",
-            letterSpacing: "-0.24px",
-          }}
+          style={linkStyle}
           href="https://google.com"
         >
           비밀번호 찾기
         </Link>
         <div style={{ width: "1px", height: "11px", backgroundColor: "#D9D9D9" }} />
         <Link
-          style={{
-            color: "#111",
-            fontSize: "12px",
-            fontStyle: "normal",
-            fontWeight: "500",
-            lineHeight: "140%",
-            letterSpacing: "-0.24px",
-          }}
+          style={linkStyle}
           href="https://google.com"
         >
           회원가입
         </Link>
       </div>
     );
   },
 };

참고: Storybook 스토리에서는 플레이스홀더 URL이 일반적이지만, 실제 구현 시 올바른 경로로 교체해야 합니다.


157-193: SNS 로그인 구분선 UI 구현

SNS 로그인 영역을 시각적으로 구분하는 UI가 구현되었습니다. 기능적으로 올바르게 동작합니다.

구분선 스타일이 중복되므로, 선택적으로 상수로 추출할 수 있습니다:

 export const SNS_계정으로_로그인: Story = {
   args: {},
   render: () => {
+    const dividerStyle = {
+      width: "100%",
+      height: "1px",
+      backgroundColor: "#D9D9D9",
+    };
+
     return (
       <div style={{ width: "360px", display: "flex", flexDirection: "row", gap: "12px", alignItems: "center" }}>
-        <div
-          style={{
-            width: "100%",
-            height: "1px",
-            backgroundColor: "#D9D9D9",
-          }}
-        />
+        <div style={dividerStyle} />
         <div
           style={{
             color: "#A7A7A7",
             fontSize: "12px",
             fontStyle: "normal",
             fontWeight: "500",
             lineHeight: "140%",
             letterSpacing: "-0.24px",
             textAlign: "center",
             minWidth: "fit-content",
           }}
         >
           SNS 계정으로 로그인
         </div>
-        <div
-          style={{
-            width: "100%",
-            height: "1px",
-            backgroundColor: "#D9D9D9",
-          }}
-        />
+        <div style={dividerStyle} />
       </div>
     );
   },
 };
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64c7521 and 125afb8.

📒 Files selected for processing (2)
  • apps/web/src/views/login/login.stories.tsx (2 hunks)
  • apps/web/src/views/register/register.stories.tsx (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/src/views/register/register.stories.tsx (2)
apps/web/src/views/login/components/TextField.tsx (1)
  • TextField (23-175)
apps/web/src/views/register/components/TopBar.tsx (1)
  • TopBar (11-64)
apps/web/src/views/login/login.stories.tsx (2)
apps/web/src/views/login/components/TextField.tsx (1)
  • TextField (23-175)
apps/web/src/views/login/components/Button.tsx (1)
  • Button (9-33)
⏰ 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 (6)
apps/web/src/views/register/register.stories.tsx (5)

2-2: 필요한 import 추가 확인

새로운 탑바 스토리에서 사용하는 ImageTopBar import가 적절하게 추가되었습니다.

Also applies to: 6-6


42-43: TextField 기능 향상 적용 완료

useValidationStatususeResetButton 속성이 추가되어 유효성 검사 상태 표시 및 리셋 기능이 활성화되었습니다.


55-55: 비밀번호 확인 기능 구현 검토

비밀번호 확인 필드가 추가되고 유효성 검사 상태 표시가 활성화되었습니다. 검증 로직은 비밀번호와 비밀번호 확인 값을 정확히 비교합니다.

참고: 비밀번호 확인을 먼저 입력한 후 비밀번호를 변경하면 불일치 에러가 표시되는데, 이는 의도된 동작입니다.

Also applies to: 71-71, 77-78, 86-86


113-113: 닉네임 필드에 유효성 검사 상태 표시 추가

닉네임 TextField에 useValidationStatus 속성이 추가되어 다른 입력 필드와 일관된 UX를 제공합니다.


120-136: TopBar 스토리 검증 완료 - 아이콘 경로 확인됨

아이콘 파일이 올바른 위치에 존재합니다: ./apps/web/public/icons/components/arrow-left-black.png

Next.js의 public 폴더 자산 참조 방식에 따라 "/icons/components/arrow-left-black.png" 경로가 올바르게 지정되었습니다. 스토리에서 TopBar 컴포넌트가 적절하게 구현되었으며, 모든 파일 참조가 유효합니다.

apps/web/src/views/login/login.stories.tsx (1)

2-2: Link 컴포넌트 import 추가

네비게이션 링크를 위한 Next.js Link 컴포넌트가 적절하게 import되었습니다.

Copy link
Member

@widse widse left a comment

Choose a reason for hiding this comment

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

@seungdeok
깔끔한 작업 감사합니다!! 참고해서 추가 작업 할게용 ㅎㅎ..!!! :)

Comment on lines +151 to +153
<button type="button" onClick={() => onChange?.("")} aria-label="초기화" style={{ cursor: "pointer" }}>
<Image src="/icons/components/reset.png" alt="초기화" width={20} height={20} />
</button>
Copy link
Member

Choose a reason for hiding this comment

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

@seungdeok
button으로 지정해서 접근성 잡아주신거 좋은 거 같아요 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants