Skip to content

[refactor] 퍼널 공통 헤더 v2 전환 및 InteriorStyle 디자인 리뉴얼#511

Open
jstar000 wants to merge 6 commits intodevelopfrom
feat/funnel-renewal/#500
Open

[refactor] 퍼널 공통 헤더 v2 전환 및 InteriorStyle 디자인 리뉴얼#511
jstar000 wants to merge 6 commits intodevelopfrom
feat/funnel-renewal/#500

Conversation

@jstar000
Copy link
Copy Markdown
Contributor

@jstar000 jstar000 commented Apr 8, 2026

📌 Summary

관련 있는 Issue를 태그해주세요. (e.g. > - #1)

해당 PR에 대한 작업 내용을 요약하여 작성해주세요.

📄 Tasks

  • 퍼널 공통 헤더 v2 전환 + InteriorStyle 디자인 리뉴얼 (이번 PR)
  • ActivityInfo UI 리뉴얼 + ActivityInfo 바텀시트 @use-funnel 오버레이 스텝에 추가 (다음 PR에 작업할 예정)

내용 정리

  • 퍼널 공통 헤더 → v2 navBar 적용
    • FunnelLayout 한 곳에서 각 스텝의 NavBar 관리(스텝별 title 매핑)
  • InteriorStyle 스텝은 v2 TextHeading(제목과 설명) + ‘다음’ ActionButton + MoodboardCard 컴포넌트 띄우도록 리뉴얼 적용, 기존 CardImage(기존 무드보드 카드 컴포넌트)는 삭제

구현 내용

1. 퍼널 NavBar v2 전환 + 스텝별 title 매핑

  • 기존 v1 @components/navBar/TitleNavBar를 v2로 교체

    • 스텝마다 다른 title 적용 ← FunnelLayout의 currentStep prop으로 구현

      // FunnelLayout.tsx
      const NAVBAR_TITLE_BY_STEP: Record<FunnelStepKey, string> = {
        FloorPlanSelect: '공간 선택하기',
        InteriorStyle: '취향 선택하기',
        ActivityInfo: '가구 선택하기',
      };
  • v2 TitleNavBar의 backLabel prop으로 "이전" 텍스트를 좌측 백버튼 옆에 표시 (전 스텝 공통)

  • 퍼널 탈출 관련 로직(퍼널 탈출 시 모달 띄우기) 관리는 추후 다른 브랜치에서 useBlocker를 사용한 방식으로 변경할 예정이에요(지금은 라우터단에서 관리하는게 아니라 브라우저 뒤로가기, navBar 뒤로가기 각각 따로 관리해서 관리 불편)

2. InteriorStyle UI 리뉴얼

  • 기존 FunnelHeader(진행률 바 + 헤더 이미지 + 텍스트) 제거, v2 TextHeading 적용

  • ‘다음’ ActionButton 적용 + buttonWrapper css 수정(’다음’ 버튼 floating용)

    • 데스크탑·모바일 모두에서 우하단 floating 요구 반영 → 44rem 프레임 기준 우하단에 2rem씩 띄우는 식으로 구현
    export const buttonWrapper = style({
      position: 'fixed',
      zIndex: zIndex.button,
      right: 'max(2rem, calc((100vw - 44rem) / 2 + 2rem))',
      bottom: '2rem',
    });

    max() 안의 식이 모바일/데스크탑을 한 번에 처리

    • 모바일(≤44rem): 100vw - 44rem이 음수 → max()2rem 선택 → 뷰포트 우측에서 2rem
    • 데스크탑(>44rem): 프레임 좌·우 여백 한쪽 + 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로 따라오는 브라우저 기본 동작이 거슬려서 막았어요.

      <img ... draggable={false} />
  • ActionButton disabled 처리

    이미지 미선택 시 "다음" 버튼이 비활성화돼야 해서 native HTML disabled를 적용했어요.

    <ActionButton
      disabled={!isDataComplete}
      onClick={handleCtaButtonClick}
    >
      다음
    </ActionButton>
    • inactive 상태 GA 로깅(logSelectMoodboardClickBtnCTAInactive)이 이번 PR에서 일시적으로 빠짐 (native disabled는 click 이벤트 자체를 차단하기 때문에 inactive 클릭 로깅을 살릴 수 없기 때문에)

      inactive 상태 GA 로깅을 살리려면 ActionButton에 visuallyDisabled prop 추가가 필요함(시각만 disabled, click은 받음, aria-disabled로 접근성 보장) → 이 PR에서 분리해서 별도 PR로 진행할 예정

    자세한 설명은 디코 스레드 참고해주세요!

다음 PR에서 작업할 것

  • ActivityInfo UI 재구성 + 퍼널 내 바텀시트 오버레이들을 퍼널 스텝에 편입

    ActivityInfo쪽에 작업해야될 내용이 꽤 많아요. API 레이어 수정 / 비즈니스 훅, 유틸 수정 / UI 리뉴얼 / @use-funnel overlay 스텝 적용까지 처리할 예정이라 다음 PR로 분리해서 별도로 작업할 예정이에요.

  • useBlocker 라우터 가드: ActivityInfo 작업과 묶거나 별도 후속 PR로 진행할 예정

  • ActionButton visuallyDisabled prop 추가: 별도 v2 디자인 시스템 PR

To Reviewer

  1. MoodboardCard 동그라미 체크박스 크기: Figma 원본은 default 20×20 / selected 24×24인데 일단 신경 쓰여서 24×24로 통일했어요. 디쌤들한테 어떻게 할 지 물어봤으니 답변 오면 확인하고 수정 필요할 시 수정할게요!
  2. inactive 로깅 일시 누락: 위 "ActionButton disabled 처리" 참고 / 별도 PR 머지 후 이벤트 로그 복원 예정

📸 Screenshot

2026-04-08.8.03.16.mov

작업한 내용에 대한 스크린샷을 첨부해주세요.

@jstar000 jstar000 self-assigned this Apr 8, 2026
@jstar000 jstar000 requested a review from a team as a code owner April 8, 2026 11:04
@jstar000 jstar000 added 🤙 지성 웹 36기 임지성 🛠️ Refactor 리팩토링 labels Apr 8, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 8, 2026

📝 Walkthrough

Walkthrough

무드보드 이미지 표현을 CardImage에서 신규 MoodboardCard로 교체하고 관련 스타일을 추가/조정했으며, FunnelLayout의 네비게이션 타이틀을 단계별 매핑으로 변경하고 여러 관련 스타일/스토리북 파일을 정리(삭제)했습니다.

Changes

Cohort / File(s) Summary
레이아웃 및 네비게이션 업데이트
src/pages/imageSetup/components/layout/FunnelLayout.tsx
TitleNavBar 임포트 경로를 v2로 변경하고 FunnelStepKey 타입 도입, 단계별 제목을 NAVBAR_TITLE_BY_STEP으로 동적 매핑; 뒤로가기 레이블을 backLabel="이전"으로 변경.
InteriorStyle 뷰 및 로직 변경
src/pages/imageSetup/steps/interiorStyle/InteriorStyle.tsx
FunnelHeader를 제거하고 TextHeading으로 대체; 분석 호출 단순화(항상 logSelectMoodboardClickBtnCTA 호출), CTA 컴포넌트를 CtaButton에서 ActionButton으로 교체하고 disabled 제어를 컴포넌트에 위임.
InteriorStyle 스타일 조정
src/pages/imageSetup/steps/interiorStyle/InteriorStyle.css.ts, src/pages/imageSetup/steps/interiorStyle/MoodBoard.css.ts
container에 gap/padding 추가(InteriorStyle) 및 headingWrapper 추가; buttonWrapper의 반응형 위치값 변경. MoodBoard의 container에서 고정 padding 제거.
무드보드 카드 신규 컴포넌트
src/pages/imageSetup/steps/interiorStyle/MoodboardCard.tsx, src/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.ts
MoodboardCard 컴포넌트 추가(버튼형, 선택/비활성 상태, selectOrder 표시) 및 해당 Vanilla Extract 스타일(카드, 이미지, 체크박스, 원형 인디케이터) 추가.
무드보드 뷰에서 CardImage → MoodboardCard 마이그레이션
src/pages/imageSetup/steps/interiorStyle/MoodBoard.tsx
CardImage 사용을 MoodboardCard로 교체(동일 props 전달).
레거시 CardImage 관련 삭제
src/shared/components/card/cardImage/CardImage.tsx, src/shared/components/card/cardImage/CardImage.css.ts, src/shared/components/card/cardImage/SkeletonCardImage.tsx, src/stories/CardImage.stories.tsx, src/stories/SkeletonCardImage.stories.tsx
기존 CardImage 컴포넌트, 스타일, 스켈레톤 컴포넌트 및 관련 Storybook 스토리 전부 삭제.
공유 컴포넌트 스타일 미세조정
src/shared/components/v2/textHeading/TextHeading.css.ts
wrapper 기본 패딩 제거, captionwhiteSpace: 'pre-line' 추가.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45분

Suggested reviewers

  • earl9rey
  • maehwasoo
  • soyyyyy
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 PR의 주요 변경사항을 정확히 반영하고 있으며, 요구된 [type] 형식을 따르고 50자 이내 조건을 만족합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed PR 설명이 변경 사항과 관련이 있으며, 구현 내용, 리뷰 포인트, 후속 작업을 구체적으로 설명하고 있습니다.

✏️ 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.

❤️ Share

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

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 8, 2026

빌드 결과

빌드 성공 🎊

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 8, 2026

🎨 Storybook 빌드 완료!

📚 Storybook: https://686a831b8e000345a949970a-mufqnwiwuz.chromatic.com/
🔍 Chromatic: https://www.chromatic.com/build?appId=686a831b8e000345a949970a&number=937

📊 빌드 정보

  • 빌드 상태: success
  • 테스트된 스토리: 3개
  • 변경된 컴포넌트: 3개

🔍 시각적 변경사항: 4개 발견

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 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".

Comment thread src/pages/imageSetup/components/layout/FunnelLayout.tsx
Comment thread src/pages/imageSetup/steps/interiorStyle/MoodboardCard.tsx Outdated
Copy link
Copy Markdown

@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: 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

📥 Commits

Reviewing files that changed from the base of the PR and between 1e9b3c0 and 12b7325.

📒 Files selected for processing (13)
  • src/pages/imageSetup/components/layout/FunnelLayout.tsx
  • src/pages/imageSetup/steps/interiorStyle/InteriorStyle.css.ts
  • src/pages/imageSetup/steps/interiorStyle/InteriorStyle.tsx
  • src/pages/imageSetup/steps/interiorStyle/MoodBoard.css.ts
  • src/pages/imageSetup/steps/interiorStyle/MoodBoard.tsx
  • src/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.ts
  • src/pages/imageSetup/steps/interiorStyle/MoodboardCard.tsx
  • src/shared/components/card/cardImage/CardImage.css.ts
  • src/shared/components/card/cardImage/CardImage.tsx
  • src/shared/components/card/cardImage/SkeletonCardImage.tsx
  • src/shared/components/v2/textHeading/TextHeading.css.ts
  • src/stories/CardImage.stories.tsx
  • src/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

Comment thread src/pages/imageSetup/components/layout/FunnelLayout.tsx
Comment thread src/pages/imageSetup/steps/interiorStyle/InteriorStyle.css.ts
Comment thread src/pages/imageSetup/steps/interiorStyle/InteriorStyle.tsx
Comment thread src/pages/imageSetup/steps/interiorStyle/MoodboardCard.tsx Outdated
- div -> button 변경으로 키보드 포커스 등 접근성 제공
- 'children', 'type'을 omit (type은 button으로 고정)
-
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 8, 2026

빌드 결과

빌드 성공 🎊

Copy link
Copy Markdown

@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

🤖 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

📥 Commits

Reviewing files that changed from the base of the PR and between 12b7325 and 40f5505.

📒 Files selected for processing (2)
  • src/pages/imageSetup/steps/interiorStyle/MoodboardCard.css.ts
  • src/pages/imageSetup/steps/interiorStyle/MoodboardCard.tsx

Comment on lines +76 to +84
variants: {
state: {
// default: 흰 stroke 빈 동그라미 20×20
default: {},
// selected: 다크 배경 24×24, 흰 숫자
selected: {},
},
},
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 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).

@jstar000 jstar000 added the 💫 Feature 기능 개발 label Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💫 Feature 기능 개발 🛠️ Refactor 리팩토링 🤙 지성 웹 36기 임지성

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] B-2 무드보드 리뉴얼 적용

1 participant