[Refactor/#132] 온보딩 디자인 및 애니메이션 개선, AuthLayout 개선 - #136
Conversation
📝 WalkthroughWalkthrough인증·온보딩 관련 컴포넌트들의 full-screen 중앙정렬 래퍼를 제거하고 인트로 애니메이션·유틸 CSS를 정리했으며, 공통 UI 컴포넌트에 디자인 토큰 클래스와 모달 종료 애니메이션 지연 언마운트 로직을 도입했습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User as User
participant Page as Page (opens Modal)
participant Modal as Modal Component
participant RemoveScroll as RemoveScroll (scroll lock)
participant FocusMgr as Focus manager
User->>Page: click open
Page->>Modal: set isOpen = true
Modal->>RemoveScroll: enabled = true (isVisible)
Modal->>FocusMgr: set focus to modal
Note right of Modal: Modal renders overlay + content\nwith "in" animation
User->>Modal: click close / backdrop
Modal->>Modal: set isOpen = false
Modal->>Modal: isClosing = true (start CLOSE_DURATION)
Modal->>RemoveScroll: keep enabled = true (isVisible)
Modal->>Modal: apply animate-modal-*-out classes
Note right of Modal: closing animation plays (~CLOSE_DURATION)
Modal->>RemoveScroll: enabled = false (after closing)
Modal->>FocusMgr: restore focus to previous element
Modal->>Page: set shouldRender = false (unmount)
(시각 요소 애니메이션 클래스는 isVisible/isClosing 상태로 전환됨. 다채로운 박스는 애니메이션 상태 표시 목적.) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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 |
📚 Storybook 배포 완료
|
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (1)
src/components/auth/flows/signup/ProfileSetupStep.tsx (1)
97-115: 동의 영역 클릭 처리에 키보드 접근성을 보강하는 게 좋겠습니다.현재
onClick이div에 걸려 있어서 “전체 행 클릭” 인터랙션은 포인터 중심입니다. 전체 영역을 액션 영역으로 유지하려면role="button",tabIndex,onKeyDown(Enter/Space)를 추가하거나, 클릭 책임을 실제button으로 모으는 쪽이 더 안전합니다.As per coding guidelines,
src/**: 7. 접근성: 시맨틱 HTML, ARIA 속성 사용 확인.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/auth/flows/signup/ProfileSetupStep.tsx` around lines 97 - 115, The clickable consent row uses a non-semantic div with an onClick handler; make it keyboard-accessible by replacing the div with a semantic button (preserve the className and onClick) or, if you must keep a div, add role="button", tabIndex={0} and an onKeyDown handler that triggers the same logic on Enter/Space; ensure type="button" when using a button and keep the existing modal-opening logic that calls openModal(MODAL_TYPES.PRIVACY) and uses watch("terms")/watch("marketing") and setValue("marketing")/setValue("terms", ..., { shouldValidate:true }) so keyboard activation behaves identically to pointer activation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/auth/flows/find-email/EnterPhoneStep.tsx`:
- Around line 164-178: The verification input and submit path allow calling
verifySMSMutate before a code was sent; update EnterPhoneStep.tsx to disable the
code field and block submission until sendCode is true: make the CommonAuthInput
disabled when !sendCode (in addition to existing isExpired logic) and add a
guard at the start of the onSubmit handler (e.g., if (!sendCode) return or show
a user-facing message) so verifySMSMutate is only invoked after a code was
actually sent; ensure references include the sendCode flag, the CommonAuthInput
usage (register("code")), and the verifySMSMutate call in onSubmit.
In `@src/components/auth/flows/signup/EnterEmailStep.tsx`:
- Around line 77-87: The disabled logic for the verification input in
EnterEmailStep.tsx is too permissive (disabled={isExpired}), allowing typing
before a code is sent; update the CommonAuthInput disabled prop to match the
other flow by using disabled={!sendCode || isExpired} so the field is disabled
until sendCode is true or when the timer expires—locate the CommonAuthInput
invocation where register("code") is spread and change the disabled expression
accordingly to keep behavior consistent with EmailVerificationStep.
In `@src/components/auth/intro/IntroAdManagement.tsx`:
- Line 29: The carousel currently duplicates PLATFORMS only twice (const
CAROUSEL_ITEMS = [...PLATFORMS, ...PLATFORMS]) which can make the looping
boundary visible when the track is shorter than the container; change this to
dynamically build CAROUSEL_ITEMS inside the IntroAdManagement component: measure
the carousel container width (or use window.innerWidth) and an item width, then
append PLATFORMS repeatedly until the computed track width exceeds the container
width plus a safety buffer (or at least twice the container width) to avoid gaps
at translateX(-50%); implement this logic in a useEffect and store the result in
state (e.g., carouselItems state) instead of a module-level const so it runs
client-side and reflows correctly.
In `@src/components/auth/intro/IntroAIAnalytics.tsx`:
- Around line 83-93: The inline transition styles on the bubble in
IntroAIAnalytics.tsx (the element using className with showBubble) prevent the
existing prefers-reduced-motion CSS from disabling animations; move the inline
style block (transitionProperty, transitionDuration, transitionTimingFunction)
into a named CSS utility/class (e.g., .ai-analytics-bubble-transition) defined
in your global CSS where the existing prefers-reduced-motion rule can override
it (set transition: none inside the media query). Then remove the inline style
and add that utility class to the element’s className so the showBubble toggles
still control visibility via classes but reduced-motion users get transitions
suppressed by CSS.
In `@src/components/auth/intro/IntroLogo.tsx`:
- Around line 6-8: The IntroLogo component's root element uses only visual
hiding (opacity/pointer-events) so screen readers still expose inactive panel
content; update the root element (the element with the className string that
uses isActive) to add aria-hidden={!isActive} so the accessibility tree is
updated when isActive is false; locate the className usage in the IntroLogo
component and add the aria-hidden attribute bound to the isActive prop.
In `@src/components/auth/intro/OnboardingIntro.tsx`:
- Around line 41-43: The indicator's width change (w-8 ↔ w-2.5) in
OnboardingIntro.tsx is not being animated because the current transition class
(transition-smooth) does not include width; update the indicator element's
className (the element that uses getIndicatorColor(index)) to use a transition
that covers width (e.g., replace or extend transition-smooth with a utility that
includes width like transition-all or a custom transition-width class) or adjust
the transition-smooth definition to include width so the width change from
getIndicatorColor is animated smoothly.
In `@src/components/common/modal/Modal.tsx`:
- Around line 43-59: The close animation currently keeps DOM via shouldRender
but still releases focus and RemoveScroll because those side effects depend only
on isOpen; change effects that control scroll lock/RemoveScroll and focus
restoration to use the combined rendering state (isOpen || isClosing) instead of
isOpen so they remain active during the CLOSE_DURATION; keep the existing
useEffect that toggles shouldRender/isClosing (with CLOSE_DURATION) to delay
unmounting, and update any focus-restore effect and RemoveScroll usage to read
(isOpen || isClosing) so focus/scroll are only released after the closing
animation completes.
In `@src/layout/main/MainLayout.tsx`:
- Line 27: The div in MainLayout.tsx uses the CSS token class "px-component-xl"
which appears missing from the theme, causing horizontal padding to be lost;
update the code by either (A) replacing "px-component-xl" in the className on
the div inside MainLayout.tsx with an existing, defined padding token (e.g.,
"px-component" or another valid token from your theme), or (B) add a matching
"component-xl" padding token to your theme/CSS (src/index.css `@theme`) so the
"px-component-xl" utility is generated—ensure the class name in MainLayout.tsx
and the token name in src/index.css match exactly.
In `@src/pages/auth/Login.tsx`:
- Around line 76-79: The login button currently allows duplicate submissions;
wire the useLogin.isPending state into the Button in Login.tsx so that when
useLogin.isPending is true the Button is disabled and shows a loading indicator,
and ensure the form's submit handler (e.g., the function using useLogin or
handleSubmit) respects that state to prevent re-entry; update the Button props
(disabled and a loading/aria-busy flag or variant) to reflect useLogin.isPending
and guard the submit handler to return early if isPending.
---
Nitpick comments:
In `@src/components/auth/flows/signup/ProfileSetupStep.tsx`:
- Around line 97-115: The clickable consent row uses a non-semantic div with an
onClick handler; make it keyboard-accessible by replacing the div with a
semantic button (preserve the className and onClick) or, if you must keep a div,
add role="button", tabIndex={0} and an onKeyDown handler that triggers the same
logic on Enter/Space; ensure type="button" when using a button and keep the
existing modal-opening logic that calls openModal(MODAL_TYPES.PRIVACY) and uses
watch("terms")/watch("marketing") and setValue("marketing")/setValue("terms",
..., { shouldValidate:true }) so keyboard activation behaves identically to
pointer activation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9c57ad1b-6e94-4a42-a800-5c8b09431912
⛔ Files ignored due to path filters (2)
.gitignoreis excluded by none and included by noneai-button-preview.htmlis excluded by none and included by none
📒 Files selected for processing (26)
src/components/auth/common/PasswordForm.tsxsrc/components/auth/flows/find-email/EnterPhoneStep.tsxsrc/components/auth/flows/find-email/ShowEmailResultStep.tsxsrc/components/auth/flows/reset-password/EmailVerificationStep.tsxsrc/components/auth/flows/signup/EnterEmailStep.tsxsrc/components/auth/flows/signup/ProfileSetupStep.tsxsrc/components/auth/intro/AiTalkBubble.tsxsrc/components/auth/intro/IntroAIAnalytics.tsxsrc/components/auth/intro/IntroAdManagement.tsxsrc/components/auth/intro/IntroLogo.tsxsrc/components/auth/intro/OnboardingIntro.tsxsrc/components/auth/skeleton/LoginPageSkeleton.tsxsrc/components/auth/skeleton/SignupEmailStepSkeleton.tsxsrc/components/auth/skeleton/SignupPageSkeleton.tsxsrc/components/common/button/Button.tsxsrc/components/common/card/Card.tsxsrc/components/common/card/InfoCard.tsxsrc/components/common/card/StatCard.tsxsrc/components/common/drawer/Drawer.tsxsrc/components/common/modal/Modal.tsxsrc/index.csssrc/layout/auth/AuthLayout.tsxsrc/layout/main/MainLayout.tsxsrc/pages/auth/Login.tsxsrc/pages/auth/Signup.tsxsrc/pages/dashboard/overview/OverviewDashboard.tsx
💤 Files with no reviewable changes (1)
- src/components/common/card/InfoCard.tsx
|
P4: 확인했습니다 수고하셨습니다!! |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/auth/intro/IntroAIAnalytics.tsx`:
- Around line 32-35: The slide wrapper in IntroAIAnalytics (the div using
isActive to toggle classes) only hides visually and via pointer-events but is
still exposed to assistive tech; update the div that uses isActive to also set
aria-hidden={!isActive} (or aria-hidden={isActive ? "false" : "true"} if JSX
string values are preferred) so inactive slides are hidden from screen readers,
and ensure any interactive children are not focusable when isActive is false
(e.g., rely on existing pointer-events-none/opacity logic plus aria-hidden to
prevent duplicate announcements).
In `@src/components/common/modal/Modal.tsx`:
- Around line 43-45: The focus effect runs too early because isVisible becomes
true before the modal DOM mounts (shouldRender is still false), causing
modalRef.current to be null and focus to remain on the background; also the
first effect triggers close logic when isOpen is false. Fix by changing the
render/focus logic so focus is applied only after the modal is actually mounted:
ensure shouldRender is set to true immediately when isOpen becomes true (so the
DOM mounts before the focus effect runs) and move/guard the focus-setting effect
to run when shouldRender && modalRef.current are truthy (instead of just
isVisible), and also guard the closing effect so it only runs when transitioning
from open→closed (e.g., check previous isOpen or isClosing) to avoid unnecessary
close logic; update references in Modal.tsx to the shouldRender, isClosing,
isVisible states and modalRef so the focus and close effects run at the correct
times.
In `@src/index.css`:
- Around line 487-500: The reduced-motion override is being trumped by the later
default animation; move the `@media` (prefers-reduced-motion: reduce) block that
defines the reduced keyframes and the .animate-fade-in-up rule (and/or the
`@keyframes` fade-in-up-reduced) so it appears after the default `@keyframes`
fade-in-up and the default .animate-fade-in-up definition in the file; ensure
the media-query contains the .animate-fade-in-up rule that uses
fade-in-up-reduced so the reduced-motion preference takes precedence.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6e36bbbe-7cec-4c39-b071-cceb205d6816
📒 Files selected for processing (8)
src/components/auth/flows/find-email/EnterPhoneStep.tsxsrc/components/auth/flows/signup/EnterEmailStep.tsxsrc/components/auth/intro/IntroAIAnalytics.tsxsrc/components/auth/intro/IntroLogo.tsxsrc/components/auth/intro/OnboardingIntro.tsxsrc/components/common/modal/Modal.tsxsrc/index.csssrc/layout/main/MainLayout.tsx
✅ Files skipped from review due to trivial changes (2)
- src/components/auth/intro/OnboardingIntro.tsx
- src/layout/main/MainLayout.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- src/components/auth/intro/IntroLogo.tsx
- src/components/auth/flows/find-email/EnterPhoneStep.tsx
- src/components/auth/flows/signup/EnterEmailStep.tsx

🚨 관련 이슈
#132
✨ 변경사항
✏️ 작업 내용
😅 미완성 작업
N/A
📢 논의 사항 및 참고 사항
N/A
Summary by CodeRabbit
릴리스 노트
스타일
버그 수정