[refactor] 퍼널 공통 헤더 v2 전환 및 InteriorStyle 디자인 리뉴얼#511
[refactor] 퍼널 공통 헤더 v2 전환 및 InteriorStyle 디자인 리뉴얼#511
Conversation
- B-2 디자인 수정을 반영해 InteriorStyle 스텝에 MoodboardCard 추가, 기존 CardImage 제거 - MoodboardCard는 공컴이 아니므로 InteriorStyle 폴더 안에 선언 - 164-240 반응형 적용
📝 WalkthroughWalkthrough무드보드 이미지 표현을 Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45분 Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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 빌드 완료!📚 Storybook: https://686a831b8e000345a949970a-mufqnwiwuz.chromatic.com/ 📊 빌드 정보
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 12b73250ce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/pages/imageSetup/steps/interiorStyle/MoodBoard.tsx (1)
50-54:⚠️ Potential issue | 🟠 Major모든 카드의 접근성 이름이 동일합니다.
MoodBoardImageItem에 설명 필드가 없으므로, 이미 전달되는selectOrder값을 활용해 각 카드마다 고유한aria-label을 제공하세요. 예:aria-label={selectOrder > 0 ?${selectOrder}번째 선택됨:이미지 ${index + 1}}. 이렇게 하면 스크린리더 사용자도 어떤 옵션을 선택하는지 명확히 구분할 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/imageSetup/steps/interiorStyle/MoodBoard.tsx` around lines 50 - 54, Currently every MoodboardCard uses the same accessible name; update the MoodboardCard (and/or MoodBoardImageItem) usage to compute a unique aria-label using the already-passed selectOrder value from getSelectOrder(image.id) and the image index: set aria-label to something like "n번째 선택됨" when selectOrder > 0 otherwise "이미지 {index+1}". Add the aria-label prop to the MoodboardCard component invocation and ensure the MoodboardCard/MoodBoardImageItem accepts and applies aria-label to the underlying interactive element so screen readers get a unique label per card.
🤖 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/pages/imageSetup/components/layout/FunnelLayout.tsx`:
- Around line 56-61: TitleNavBar in FunnelLayout always renders a back button
but onBackClick is set to undefined except for the first step, so
InteriorStyle/ActivityInfo show a non-functional "이전" control; update
FunnelLayout to either pass the real back handler (handleBackClick) for all
steps that should navigate back (use currentStep and NAVBAR_TITLE_BY_STEP to
decide) or conditionally hide the back UI by not rendering backLabel/onBackClick
when currentStep is not navigable back, ensuring components like TitleNavBar
receive a valid onBackClick or no back props so the UI matches behavior.
In `@src/pages/imageSetup/steps/interiorStyle/InteriorStyle.css.ts`:
- Around line 27-31: Replace the hardcoded "44rem" in the buttonWrapper style
with the shared layout max width token from global layout vars (e.g.,
layoutVars.maxWidth or the exported maxWidth CSS variable from global.css.ts):
import the layout token used for global maxWidth and update the right calc to
use that token (e.g., right: `max(2rem, calc((100vw - <layoutMaxWidth>) / 2 +
2rem))`) so the floating button follows the same global layout width; keep the
rest of the buttonWrapper properties unchanged.
In `@src/pages/imageSetup/steps/interiorStyle/InteriorStyle.tsx`:
- Around line 36-41: The CTA click handler currently never logs inactive clicks
because ActionButton passes native disabled to the underlying <button>
(ActionButton) so onClick in handleCtaButtonClick never fires when
disabled={!isDataComplete}; fix by either (A) adding a visuallyDisabled boolean
prop to ActionButton that stops native disabled on the <button> and renders a
visual disabled state while still allowing onClick to run, then update
handleCtaButtonClick to call logSelectMoodboardClickBtnCTAInactive when
isDataComplete is false and logSelectMoodboardClickBtnCTA when true, or (B)
implement a thin transparent overlay layer sitting above the disabled button
that captures clicks and calls logSelectMoodboardClickBtnCTAInactive when
isDataComplete is false (and forwards to handleNext when true), ensuring unique
identifiers used here are ActionButton, handleCtaButtonClick,
logSelectMoodboardClickBtnCTAInactive, logSelectMoodboardClickBtnCTA, and
isDataComplete so the change is easy to locate.
In `@src/pages/imageSetup/steps/interiorStyle/MoodboardCard.tsx`:
- Around line 3-8: The component currently defines MoodboardCardProps extends
React.ComponentProps<'div'> and renders a clickable div, which is not keyboard
accessible and also doesn't forward the declared props; change the prop type to
React.ComponentPropsWithoutRef<'button'> (keep src, alt, selectOrder?,
disabled?, onClick?), render a <button type="button"> instead of a div, spread
the incoming props onto the button, pass the disabled prop through, and add
appropriate semantics like aria-pressed={Boolean(selectOrder)}; ensure the
component uses the existing onClick handler and still displays selectOrder when
present.
---
Outside diff comments:
In `@src/pages/imageSetup/steps/interiorStyle/MoodBoard.tsx`:
- Around line 50-54: Currently every MoodboardCard uses the same accessible
name; update the MoodboardCard (and/or MoodBoardImageItem) usage to compute a
unique aria-label using the already-passed selectOrder value from
getSelectOrder(image.id) and the image index: set aria-label to something like
"n번째 선택됨" when selectOrder > 0 otherwise "이미지 {index+1}". Add the aria-label
prop to the MoodboardCard component invocation and ensure the
MoodboardCard/MoodBoardImageItem accepts and applies aria-label to the
underlying interactive element so screen readers get a unique label per card.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 38047366-071f-40b2-bc6b-9a795593a866
📒 Files selected for processing (13)
src/pages/imageSetup/components/layout/FunnelLayout.tsxsrc/pages/imageSetup/steps/interiorStyle/InteriorStyle.css.tssrc/pages/imageSetup/steps/interiorStyle/InteriorStyle.tsxsrc/pages/imageSetup/steps/interiorStyle/MoodBoard.css.tssrc/pages/imageSetup/steps/interiorStyle/MoodBoard.tsxsrc/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.tssrc/pages/imageSetup/steps/interiorStyle/MoodboardCard.tsxsrc/shared/components/card/cardImage/CardImage.css.tssrc/shared/components/card/cardImage/CardImage.tsxsrc/shared/components/card/cardImage/SkeletonCardImage.tsxsrc/shared/components/v2/textHeading/TextHeading.css.tssrc/stories/CardImage.stories.tsxsrc/stories/SkeletonCardImage.stories.tsx
💤 Files with no reviewable changes (6)
- src/pages/imageSetup/steps/interiorStyle/MoodBoard.css.ts
- src/shared/components/card/cardImage/SkeletonCardImage.tsx
- src/stories/CardImage.stories.tsx
- src/stories/SkeletonCardImage.stories.tsx
- src/shared/components/card/cardImage/CardImage.css.ts
- src/shared/components/card/cardImage/CardImage.tsx
- div -> button 변경으로 키보드 포커스 등 접근성 제공 - 'children', 'type'을 omit (type은 button으로 고정) -
빌드 결과빌드 성공 🎊 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.ts`:
- Around line 76-84: 주석과 구현 불일치 및 불필요한 빈 variants 정리:
src/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.ts에서 circle 레시피의
주석(현재 "20×20")을 PR 스펙과 실제 구현(2.4rem / 24×24)에 맞게 수정하고, checkbox 레시피의
variants.state에 빈 객체들(예: default, selected)이 남아있는 경우 실제 스타일 차이가 checkbox가 아닌
circle에서만 처리된다면 해당 빈 variants를 제거하거나 checkbox 레시피에 의도를 설명하는 주석을 추가해 불필요한 빈
variants가 남지 않도록 정리하세요 (참조 심볼: circle 레시피, checkbox 레시피, variants.state).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: c4ed3c4f-18b8-4652-a7a3-9ede39d7fa75
📒 Files selected for processing (2)
src/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.tssrc/pages/imageSetup/steps/interiorStyle/MoodboardCard.tsx
| variants: { | ||
| state: { | ||
| // default: 흰 stroke 빈 동그라미 20×20 | ||
| default: {}, | ||
| // selected: 다크 배경 24×24, 흰 숫자 | ||
| selected: {}, | ||
| }, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
주석과 실제 구현 불일치 + 빈 variants 정리 필요
Line 78의 주석에 "20×20"이라고 되어 있지만, circle 레시피의 실제 구현은 2.4rem (24px)입니다. PR 목표에 명시된 "24×24로 통일" 스펙과 코드는 일치하므로, 주석을 수정해 주세요.
또한 checkbox 레시피의 state variants가 모두 빈 객체입니다. 실제 스타일 차이가 circle 레시피에서만 처리된다면, 불필요한 variants를 제거하거나 주석으로 의도를 명확히 해주세요.
💡 제안된 수정
export const checkbox = recipe({
base: {
position: 'absolute',
top: 0,
right: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
border: 'none',
background: 'transparent',
pointerEvents: 'none',
padding: unitVars.unit.gapPadding['400'],
},
variants: {
state: {
- // default: 흰 stroke 빈 동그라미 20×20
+ // 스타일 차이는 circle 레시피에서 처리
default: {},
- // selected: 다크 배경 24×24, 흰 숫자
selected: {},
},
},
});🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.ts` around lines
76 - 84, 주석과 구현 불일치 및 불필요한 빈 variants 정리:
src/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.ts에서 circle 레시피의
주석(현재 "20×20")을 PR 스펙과 실제 구현(2.4rem / 24×24)에 맞게 수정하고, checkbox 레시피의
variants.state에 빈 객체들(예: default, selected)이 남아있는 경우 실제 스타일 차이가 checkbox가 아닌
circle에서만 처리된다면 해당 빈 variants를 제거하거나 checkbox 레시피에 의도를 설명하는 주석을 추가해 불필요한 빈
variants가 남지 않도록 정리하세요 (참조 심볼: circle 레시피, checkbox 레시피, variants.state).
📌 Summary
해당 PR에 대한 작업 내용을 요약하여 작성해주세요.
📄 Tasks
내용 정리
구현 내용
1. 퍼널 NavBar v2 전환 + 스텝별 title 매핑
기존 v1
@components/navBar/TitleNavBar를 v2로 교체스텝마다 다른 title 적용 ← FunnelLayout의
currentStepprop으로 구현v2 TitleNavBar의
backLabelprop으로 "이전" 텍스트를 좌측 백버튼 옆에 표시 (전 스텝 공통)퍼널 탈출 관련 로직(퍼널 탈출 시 모달 띄우기) 관리는 추후 다른 브랜치에서
useBlocker를 사용한 방식으로 변경할 예정이에요(지금은 라우터단에서 관리하는게 아니라 브라우저 뒤로가기, navBar 뒤로가기 각각 따로 관리해서 관리 불편)2. InteriorStyle UI 리뉴얼
기존 FunnelHeader(진행률 바 + 헤더 이미지 + 텍스트) 제거, v2 TextHeading 적용
‘다음’ ActionButton 적용 + buttonWrapper css 수정(’다음’ 버튼 floating용)
max()안의 식이 모바일/데스크탑을 한 번에 처리100vw - 44rem이 음수 →max()가2rem선택 → 뷰포트 우측에서 2rem⇒ 디바이스 영역이 아닌 곳에 버튼이 float되는 문제 해결
MoodboardCard 적용
기존 CardImage 컴포넌트 완전 제거 → 이번에 추가한 MoodboardCard 컴포넌트로 대체
다른 페이지에서 재사용될 일이 없는 컴포넌트라
src/pages/imageSetup/steps/interiorStyle/안에 선언카드 사이즈 반응형 적용 (width: 100% + aspectRatio(16.4rem/24rem)
접근성을 위해
<button>으로 선언(기존에는<div>), children/type omit으로 children 전달 방지 및 type="button"으로 고정데스크탑 드래그 방지
데스크탑 마우스로 카드를 클릭한 채 드래그하면 이미지가 ghost로 따라오는 브라우저 기본 동작이 거슬려서 막았어요.
ActionButton disabled 처리
이미지 미선택 시 "다음" 버튼이 비활성화돼야 해서 native HTML
disabled를 적용했어요.inactive 상태 GA 로깅(
logSelectMoodboardClickBtnCTAInactive)이 이번 PR에서 일시적으로 빠짐 (native disabled는 click 이벤트 자체를 차단하기 때문에 inactive 클릭 로깅을 살릴 수 없기 때문에)inactive 상태 GA 로깅을 살리려면 ActionButton에
visuallyDisabledprop 추가가 필요함(시각만 disabled, click은 받음, aria-disabled로 접근성 보장) → 이 PR에서 분리해서 별도 PR로 진행할 예정자세한 설명은 디코 스레드 참고해주세요!
다음 PR에서 작업할 것
ActivityInfo UI 재구성 + 퍼널 내 바텀시트 오버레이들을 퍼널 스텝에 편입
ActivityInfo쪽에 작업해야될 내용이 꽤 많아요. API 레이어 수정 / 비즈니스 훅, 유틸 수정 / UI 리뉴얼 / @use-funnel overlay 스텝 적용까지 처리할 예정이라 다음 PR로 분리해서 별도로 작업할 예정이에요.
useBlocker 라우터 가드: ActivityInfo 작업과 묶거나 별도 후속 PR로 진행할 예정
ActionButton
visuallyDisabledprop 추가: 별도 v2 디자인 시스템 PRTo Reviewer
📸 Screenshot
2026-04-08.8.03.16.mov
작업한 내용에 대한 스크린샷을 첨부해주세요.