Conversation
Walkthrough로그인 페이지, 온보딩, 스토리, 가게 검색 등 주요 UI 컴포넌트의 스타일과 구조가 QA 피드백에 따라 다수 수정되었습니다. 온보딩 인터랙션에 슬라이더가 도입되었고, 스토리/가게 검색/스토리 등록 등에서 UI 개선 및 위치 변경, 설명 추가, 스타일 조정이 이루어졌습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant LoginPage
participant ImageComponent
User->>LoginPage: 페이지 방문
LoginPage->>ImageComponent: 배경 이미지 렌더링 (Image, fill, priority)
LoginPage->>User: 로그인 UI 표시
sequenceDiagram
participant User
participant ServiceIntroBottomSheet
participant Slider
User->>ServiceIntroBottomSheet: 온보딩 열기
ServiceIntroBottomSheet->>Slider: 슬라이더 초기화
User->>Slider: 스와이프/탭/다음 클릭
Slider->>ServiceIntroBottomSheet: beforeChange(currentIndex)
ServiceIntroBottomSheet->>Slider: slickGoTo/Next 등 제어
Slider->>User: 애니메이션 적용된 온보딩 내용 표시
sequenceDiagram
participant User
participant SearchStoreBottomSheet
User->>SearchStoreBottomSheet: 검색 입력
SearchStoreBottomSheet->>SearchStoreBottomSheet: isTyping = true
SearchStoreBottomSheet->>SearchStoreBottomSheet: debounce 후 isTyping = false
SearchStoreBottomSheet->>User: 검색 결과 or 로딩 표시
SearchStoreBottomSheet->>User: "서울 지역만 검색 가능" 안내 표시
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20분 Assessment against linked issues
Assessment against linked issues: Out-of-scope changes(해당 변경사항 없음) Possibly related PRs
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
🎨 Storybook Preview: https://685a32a1c0bbd269fdb67af4-cgycdsinir.chromatic.com/ |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
src/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.tsx (2)
31-36: 사용하지 않는 매개변수 제거 권장
beforeChange콜백에서current매개변수를 사용하지 않으므로 언더스코어로 표시하는 것이 좋습니다.- beforeChange: (current: number, next: number) => { + beforeChange: (_current: number, next: number) => { setCurrentIndex(next); },
113-113: 이미지 우선순위 설정 확인모든 슬라이드 이미지에
priority속성을 설정했는데, 이는 모든 이미지를 즉시 로드하게 됩니다. 첫 번째 슬라이드 이미지만 우선순위를 설정하는 것이 성능상 더 효율적일 수 있습니다.<Image width={335} height={252} src={content.imageSrc} alt={content.imageAlt} - priority + priority={index === 0} />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
public/images/login-background.pngis excluded by!**/*.pngsrc/assets/info.svgis excluded by!**/*.svg
📒 Files selected for processing (16)
src/app/(auth)/login/_styles/Login.css.ts(1 hunks)src/app/(auth)/login/page.tsx(1 hunks)src/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.css.ts(3 hunks)src/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.tsx(3 hunks)src/app/(home)/_components/Story/AddStoryAvatar/AddStoryAvatar.css.ts(1 hunks)src/app/(home)/_components/Story/Story.css.ts(1 hunks)src/app/(home)/_components/Story/StoryList/StoryList.css.ts(1 hunks)src/app/(home)/_components/Story/StoryList/StoryList.tsx(1 hunks)src/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.css.ts(2 hunks)src/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.tsx(5 hunks)src/app/(store)/stores/register/_components/RegisterFunnel/_components/StoreInfoStep/StoreInfoStep.tsx(1 hunks)src/app/story/[id]/_components/StoryDetailContent/StoryDetailContent.css.ts(0 hunks)src/app/story/[id]/_components/StoryDetailContent/StoryDetailContent.tsx(3 hunks)src/app/story/register/_components/StorySearchStore/StorySearchStore.tsx(1 hunks)src/app/story/register/page.tsx(2 hunks)src/components/ui/TextField/TextField.tsx(2 hunks)
💤 Files with no reviewable changes (1)
- src/app/story/[id]/_components/StoryDetailContent/StoryDetailContent.css.ts
🧰 Additional context used
📓 Path-based instructions (3)
{src/styles/**/*.css.ts,src/app/**/_components/**/*.css.ts,src/components/**/*.css.ts}
📄 CodeRabbit Inference Engine (.cursor/rules/nextjs-folder-structure.mdc)
Style files must use camelCase naming with the
.css.tsextension (e.g.,Button.css.ts,theme.css.ts).
Files:
src/app/(home)/_components/Story/Story.css.tssrc/app/(home)/_components/Story/AddStoryAvatar/AddStoryAvatar.css.tssrc/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.css.tssrc/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.css.tssrc/app/(home)/_components/Story/StoryList/StoryList.css.ts
src/**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/nextjs-folder-structure.mdc)
All files must use TypeScript.
Files:
src/app/(home)/_components/Story/Story.css.tssrc/app/(auth)/login/page.tsxsrc/app/(home)/_components/Story/AddStoryAvatar/AddStoryAvatar.css.tssrc/app/story/register/_components/StorySearchStore/StorySearchStore.tsxsrc/app/(auth)/login/_styles/Login.css.tssrc/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.tsxsrc/app/(home)/_components/Story/StoryList/StoryList.tsxsrc/components/ui/TextField/TextField.tsxsrc/app/story/[id]/_components/StoryDetailContent/StoryDetailContent.tsxsrc/app/story/register/page.tsxsrc/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.css.tssrc/app/(store)/stores/register/_components/RegisterFunnel/_components/StoreInfoStep/StoreInfoStep.tsxsrc/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.css.tssrc/app/(home)/_components/Story/StoryList/StoryList.css.tssrc/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.tsx
{src/app/**/_components/**/*.tsx,src/components/**/*.tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/nextjs-folder-structure.mdc)
Component files must use PascalCase naming (e.g.,
Button.tsx,DomainLayout.tsx).
Files:
src/app/story/register/_components/StorySearchStore/StorySearchStore.tsxsrc/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.tsxsrc/app/(home)/_components/Story/StoryList/StoryList.tsxsrc/components/ui/TextField/TextField.tsxsrc/app/story/[id]/_components/StoryDetailContent/StoryDetailContent.tsxsrc/app/(store)/stores/register/_components/RegisterFunnel/_components/StoreInfoStep/StoreInfoStep.tsxsrc/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.tsx
🧠 Learnings (4)
📚 Learning: applies to {src/app/**/_components/*.css.ts,src/components/*.css.ts} : component-specific styles sho...
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-07-20T14:21:47.408Z
Learning: Applies to {src/app/**/_components/*.css.ts,src/components/*.css.ts} : Component-specific styles should be co-located with the component file.
Applied to files:
src/app/(home)/_components/Story/Story.css.tssrc/app/(home)/_components/Story/AddStoryAvatar/AddStoryAvatar.css.tssrc/app/(auth)/login/_styles/Login.css.tssrc/app/(home)/_components/Story/StoryList/StoryList.tsxsrc/app/story/[id]/_components/StoryDetailContent/StoryDetailContent.tsxsrc/app/story/register/page.tsxsrc/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.css.tssrc/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.css.tssrc/app/(home)/_components/Story/StoryList/StoryList.css.ts
📚 Learning: applies to {src/styles/**/*.css.ts,src/app/**/_components/**/*.css.ts,src/components/**/*.css.ts} : ...
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-07-20T14:21:47.408Z
Learning: Applies to {src/styles/**/*.css.ts,src/app/**/_components/**/*.css.ts,src/components/**/*.css.ts} : Style files must use camelCase naming with the `.css.ts` extension (e.g., `Button.css.ts`, `theme.css.ts`).
Applied to files:
src/app/(home)/_components/Story/Story.css.tssrc/app/(home)/_components/Story/AddStoryAvatar/AddStoryAvatar.css.tssrc/app/(auth)/login/_styles/Login.css.tssrc/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.css.tssrc/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.css.tssrc/app/(home)/_components/Story/StoryList/StoryList.css.ts
📚 Learning: applies to src/styles/*.css.ts : global styles should be placed in the `styles/` folder, using vanil...
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-07-20T14:21:47.408Z
Learning: Applies to src/styles/*.css.ts : Global styles should be placed in the `styles/` folder, using vanilla-extract.
Applied to files:
src/app/(auth)/login/_styles/Login.css.tssrc/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.css.tssrc/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.css.tssrc/app/(home)/_components/Story/StoryList/StoryList.css.ts
📚 Learning: applies to src/app/**/_constants/*.ts : domain-specific constants should be defined in `_constants` ...
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-07-20T14:21:47.408Z
Learning: Applies to src/app/**/_constants/*.ts : Domain-specific constants should be defined in `_constants` folders.
Applied to files:
src/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.css.ts
🧬 Code Graph Analysis (2)
src/components/ui/TextField/TextField.tsx (1)
src/components/ui/TextField/TextField.css.ts (1)
helperText(64-78)
src/app/(home)/_components/Story/StoryList/StoryList.css.ts (1)
src/app/(home)/_components/Story/Story.css.ts (2)
storyItem(20-22)storyImage(14-18)
🔇 Additional comments (26)
src/components/ui/TextField/TextField.tsx (2)
14-14: 헬퍼 텍스트 타입 확장이 적절합니다
helperTextprop의 타입을string | ReactNode로 확장한 것은 좋은 개선사항입니다. 이를 통해 아이콘이나 서식이 적용된 텍스트 등 더 풍부한 콘텐츠를 표시할 수 있게 되었습니다.
67-69: HTML 요소 변경이 적절합니다
<p>태그에서<div>태그로 변경한 것은 올바른 접근입니다. ReactNode 타입을 지원하기 위해서는 더 유연한 컨테이너가 필요하며,<div>가 아이콘이나 다른 요소들을 포함할 수 있어 적절한 선택입니다.src/app/story/register/_components/StorySearchStore/StorySearchStore.tsx (1)
3-3: 입력 필드 포커스 관리 단순화가 적절합니다
useRef와blur()호출을 제거한 것은 좋은 리팩토링입니다. 명시적인 포커스 해제 로직을 제거함으로써 컴포넌트가 더 단순해졌고, 기능은 그대로 유지됩니다. 이는 StoreInfoStep 컴포넌트와 일관된 패턴을 따르고 있습니다.Also applies to: 20-22
src/app/(store)/stores/register/_components/RegisterFunnel/_components/StoreInfoStep/StoreInfoStep.tsx (1)
2-2: 입력 필드 포커스 관리 일관성 있게 개선되었습니다다른 컴포넌트와 마찬가지로
useRef와 수동blur()호출을 제거한 것은 좋은 개선사항입니다. 오버레이 열기 로직이 단순화되었으며, 일관된 패턴을 유지하고 있습니다.Also applies to: 70-82
src/app/story/register/page.tsx (1)
9-9: 레이아웃 개선이 UX 향상에 기여합니다컴포넌트 순서를 재배치하고
Spacer를 추가한 것은 좋은 개선사항입니다. 이미지 미리보기 → 가게 선택 → 설명 입력 순서로 배치하여 더 자연스러운 사용자 플로우를 만들었습니다.Also applies to: 78-80
src/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.css.ts (1)
3-3: 새로운 스타일 정의가 프로젝트 표준을 잘 따르고 있습니다
semanticimport 추가와 새로운 헬퍼 텍스트 스타일들이 잘 구현되었습니다.helperTextWrapper의 flexbox 레이아웃과 적절한 gap,infoIcon의 시맨틱 컬러 사용이 디자인 시스템을 일관성 있게 활용하고 있습니다.Also applies to: 26-33
src/app/(search)/_components/SearchStoreBottomSheet/SearchStoreBottomSheet.tsx (7)
10-10: 새로운 아이콘 import 확인됨InfoIcon 추가가 적절하며, 헬퍼 텍스트에서 사용되는 것을 확인했습니다.
68-68: isTyping 상태 추가 확인사용자가 타이핑 중일 때 즉시 로딩 상태를 표시하기 위한 상태 변수가 적절히 추가되었습니다.
82-82: 타이핑 상태 관리 로직 개선입력 변경 시 즉시
isTyping을true로 설정하고, 입력이 비어있을 때false로 리셋하는 로직이 올바르게 구현되어 QA에서 지적된 2초 공백 화면 문제를 해결합니다.Also applies to: 87-87
73-73: 디바운스 완료 시 타이핑 상태 리셋디바운스된 검색이 실행될 때
isTyping을false로 설정하여 상태 관리가 일관성 있게 처리됩니다.
120-120: 검색 상태 조건 로직 개선
isSearching조건에isTyping상태를 포함하여 사용자가 타이핑하는 즉시 스켈레톤 UI가 표시되도록 개선되었습니다. 이는 QA 피드백을 반영한 적절한 개선사항입니다.
161-168: 헬퍼 텍스트 구조 개선ReactNode 타입을 활용하여 아이콘과 텍스트를 포함한 리치 헬퍼 텍스트가 구현되었습니다. 서울 지역 제한에 대한 안내 메시지가 사용자에게 명확히 전달됩니다.
139-169: autoFocus 속성 제거 확인 완료
rg명령어를 통해SearchStoreBottomSheet.tsx파일 내에 더 이상autoFocus속성이 사용되지 않음을 확인했습니다. 모바일 바텀시트 확장 문제는 해당 변경으로 해결된 것으로 보입니다.src/app/(auth)/login/_styles/Login.css.ts (1)
25-34:position: "relative"추가 적절 – 자식 absolute 요소 기준점 확보
logoWrapper에 stacking context가 생겨Image·아이콘이 의도한 영역에 정확히 배치됩니다. 추가적인 부작용은 없어 보이며 변경 사항에 동의합니다.src/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.css.ts (3)
9-11: 변경사항이 적절합니다
titleWrapper를iconWrapper로 변경한 것은 실제 용도를 더 명확하게 반영합니다.
41-41: padding 제거로 인한 레이아웃 확인 필요
body스타일에padding: 0을 추가했는데, 이로 인해 콘텐츠가 컨테이너 가장자리에 붙을 수 있습니다. 슬라이더 레이아웃을 위한 의도적인 변경이라면 문제없지만, 모바일 화면에서 여백이 충분한지 확인이 필요합니다.
44-52: 슬라이더 관련 스타일 추가 확인새로 추가된
sliderContainer와imageWrapper스타일이 react-slick 통합을 위해 적절하게 구성되었습니다.src/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.tsx (1)
5-6: import 구문 정리
Spacer컴포넌트를 새로 추가했고,react-slick라이브러리를 올바르게 import했습니다.Also applies to: 12-12
src/app/(home)/_components/Story/AddStoryAvatar/AddStoryAvatar.css.ts (1)
38-38: 스토리 추가 아이콘 크기 증가가 올바르게 구현되었습니다.패딩을
0.5rem에서0.3rem으로 줄여서 고정된2.1rem컨테이너 내에서 아이콘의 실제 표시 영역을 늘렸습니다. 이는 PR 목표인 "+ 아이콘 크기 증대"를 정확히 달성합니다.src/app/story/[id]/_components/StoryDetailContent/StoryDetailContent.tsx (3)
65-65: 이미지 스타일링 방식 개선이 적절합니다.CSS 클래스에서 인라인 prop으로
objectFit설정을 변경한 것은 다른 컴포넌트들과 일관된 패턴을 따르며, 이미지 스타일링을 더 명확하게 관리할 수 있게 합니다.
75-75: 설명 조건부 렌더링 개선이 좋습니다.옵셔널 체이닝 대신 엄격한 조건 검사를 사용하여
story.description의 존재를 더 명확하게 확인합니다.
131-137: 그라디언트 오버레이 항상 표시 요구사항이 올바르게 구현되었습니다.PR 목표에 따라 사용자 클릭 전에도 그라디언트 오버레이가 적용되도록
motion.div를 조건부가 아닌 항상 렌더링하도록 변경했습니다. 이는 스토리 설명에 일관된 시각적 효과를 제공합니다.src/app/(home)/_components/Story/StoryList/StoryList.css.ts (2)
13-17: 이미지 내부 래퍼 스타일이 적절합니다.흰색 배경과 패딩을 통해 그라디언트 테두리와 이미지 사이의 시각적 분리를 제공하는 것이 좋은 접근입니다.
19-23: 이미지 스타일 단순화가 좋습니다.
objectFit속성을 CSS에서 제거하고 컴포넌트에서 직접 관리하도록 한 것이 다른 파일들과 일관된 패턴을 따릅니다.src/app/(home)/_components/Story/StoryList/StoryList.tsx (1)
28-37: 이미지 구조 개선이 CSS 변경사항과 완벽하게 일치합니다.새로운
storyImageInner래퍼 div를 추가하여 그라디언트 테두리 기능을 구현하고,objectFit속성을 인라인 prop으로 이동한 것이 다른 컴포넌트들과 일관된 패턴을 따릅니다. 이는 PR 목표인 "보기 여부와 관계없이 스토리에 그라디언트 테두리 추가"를 올바르게 구현합니다.src/app/(home)/_components/Story/Story.css.ts (1)
7-7: 스토리 컨테이너 높이 조정이 적절합니다.
9rem에서9.5rem으로 높이를 증가시킨 것은 새로운 그라디언트 테두리와 패딩 변경사항을 수용하기 위한 합리적인 조정입니다. 전체적인 UI 개선사항과 잘 조화됩니다.
| <Image | ||
| src='/images/login-background.png' | ||
| alt='로그인 배경화면' | ||
| fill | ||
| priority | ||
| /> | ||
|
|
There was a problem hiding this comment.
💡 Verification agent
❓ Verification inconclusive
fill 이미지에 sizes 누락 – Next.js 경고 및 불필요한 이미지 다운로드 가능성
next/image에서 fill 사용 시 sizes 속성이 없으면 빌드/런타임 경고가 발생하고, 뷰포트보다 큰 이미지가 내려받혀 초기 로딩이 느려질 수 있습니다.
아래와 같이 sizes="100vw"(또는 적절한 미디어쿼리) 추가를 권장합니다.
<Image
src='/images/login-background.png'
alt='로그인 배경화면'
fill
+ sizes='100vw'
priority
/>fill 속성 사용 시 sizes 누락으로 인한 경고 및 불필요한 큰 이미지 다운로드 예방
Next.js에서 fill 레이아웃을 사용할 때 sizes를 지정하지 않으면 빌드/런타임 경고가 발생하고, 뷰포트보다 큰 이미지를 내려받아 초기 로딩 속도가 느려질 수 있습니다.
src/app/(auth)/login/page.tsx 파일의 <Image> 컴포넌트에 sizes="100vw"(또는 적절한 미디어쿼리)를 추가해주세요.
- 파일: src/app/(auth)/login/page.tsx
- 위치:
<Image>컴포넌트 (fill속성 사용 부분`)
<Image
src='/images/login-background.png'
alt='로그인 배경화면'
fill
+ sizes='100vw'
priority
/>📝 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.
| <Image | |
| src='/images/login-background.png' | |
| alt='로그인 배경화면' | |
| fill | |
| priority | |
| /> | |
| <Image | |
| src='/images/login-background.png' | |
| alt='로그인 배경화면' | |
| fill | |
| sizes='100vw' | |
| priority | |
| /> |
🤖 Prompt for AI Agents
In src/app/(auth)/login/page.tsx around lines 25 to 31, the <Image> component
uses the fill attribute but lacks the sizes attribute, causing build/runtime
warnings and potentially downloading unnecessarily large images. Add
sizes="100vw" to the <Image> component to specify the image size relative to the
viewport width, preventing these issues and improving loading performance.
| {INTRO_STEP_CONTENTS.map(content => ( | ||
| <> | ||
| <AnimatePresence mode='wait'> | ||
| <motion.div | ||
| className={styles.title} | ||
| initial={{ opacity: 0, y: 10 }} | ||
| animate={{ opacity: 1, y: 0 }} | ||
| exit={{ opacity: 0, y: -10 }} | ||
| transition={{ duration: 0.3 }} | ||
| > | ||
| <Text typo='title1Bd' className={styles.mainTitle}> | ||
| {content.title} | ||
| </Text> | ||
| <Text typo='body2Rg' color='neutral.50'> | ||
| {content.subtitle} | ||
| </Text> | ||
| </motion.div> | ||
| </AnimatePresence> | ||
|
|
||
| <Spacer size={28} /> | ||
|
|
||
| <AnimatePresence mode='wait'> | ||
| <motion.div | ||
| initial={{ opacity: 0, scale: 0.95 }} | ||
| animate={{ opacity: 1, scale: 1 }} | ||
| exit={{ opacity: 0, scale: 0.95 }} | ||
| transition={{ duration: 0.3 }} | ||
| className={styles.imageWrapper} | ||
| > | ||
| <Image | ||
| width={335} | ||
| height={252} | ||
| src={content.imageSrc} | ||
| alt={content.imageAlt} | ||
| priority | ||
| /> | ||
| </motion.div> | ||
| </AnimatePresence> | ||
| </> | ||
| ))} |
There was a problem hiding this comment.
슬라이더 내부 Fragment 및 애니메이션 구조 검토 필요
현재 구현에 몇 가지 잠재적 문제가 있습니다:
Slider컴포넌트의 직접 자식으로 Fragment(<>)를 사용하면 슬라이더가 제대로 작동하지 않을 수 있습니다.AnimatePresence가 map 내부에 있어 각 슬라이드마다 별도의 애니메이션 컨텍스트가 생성됩니다.
다음과 같이 수정을 제안합니다:
- {INTRO_STEP_CONTENTS.map(content => (
- <>
- <AnimatePresence mode='wait'>
- <motion.div
+ {INTRO_STEP_CONTENTS.map((content, index) => (
+ <div key={index}>
+ <motion.div
className={styles.title}
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.3 }}
>
<Text typo='title1Bd' className={styles.mainTitle}>
{content.title}
</Text>
<Text typo='body2Rg' color='neutral.50'>
{content.subtitle}
</Text>
</motion.div>
- </AnimatePresence>
<Spacer size={28} />
- <AnimatePresence mode='wait'>
- <motion.div
+ <motion.div
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.95 }}
transition={{ duration: 0.3 }}
className={styles.imageWrapper}
>
<Image
width={335}
height={252}
src={content.imageSrc}
alt={content.imageAlt}
priority
/>
</motion.div>
- </AnimatePresence>
- </>
+ </div>
))}📝 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.
| {INTRO_STEP_CONTENTS.map(content => ( | |
| <> | |
| <AnimatePresence mode='wait'> | |
| <motion.div | |
| className={styles.title} | |
| initial={{ opacity: 0, y: 10 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| exit={{ opacity: 0, y: -10 }} | |
| transition={{ duration: 0.3 }} | |
| > | |
| <Text typo='title1Bd' className={styles.mainTitle}> | |
| {content.title} | |
| </Text> | |
| <Text typo='body2Rg' color='neutral.50'> | |
| {content.subtitle} | |
| </Text> | |
| </motion.div> | |
| </AnimatePresence> | |
| <Spacer size={28} /> | |
| <AnimatePresence mode='wait'> | |
| <motion.div | |
| initial={{ opacity: 0, scale: 0.95 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| exit={{ opacity: 0, scale: 0.95 }} | |
| transition={{ duration: 0.3 }} | |
| className={styles.imageWrapper} | |
| > | |
| <Image | |
| width={335} | |
| height={252} | |
| src={content.imageSrc} | |
| alt={content.imageAlt} | |
| priority | |
| /> | |
| </motion.div> | |
| </AnimatePresence> | |
| </> | |
| ))} | |
| {INTRO_STEP_CONTENTS.map((content, index) => ( | |
| <div key={index}> | |
| <motion.div | |
| className={styles.title} | |
| initial={{ opacity: 0, y: 10 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| exit={{ opacity: 0, y: -10 }} | |
| transition={{ duration: 0.3 }} | |
| > | |
| <Text typo='title1Bd' className={styles.mainTitle}> | |
| {content.title} | |
| </Text> | |
| <Text typo='body2Rg' color='neutral.50'> | |
| {content.subtitle} | |
| </Text> | |
| </motion.div> | |
| <Spacer size={28} /> | |
| <motion.div | |
| initial={{ opacity: 0, scale: 0.95 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| exit={{ opacity: 0, scale: 0.95 }} | |
| transition={{ duration: 0.3 }} | |
| className={styles.imageWrapper} | |
| > | |
| <Image | |
| width={335} | |
| height={252} | |
| src={content.imageSrc} | |
| alt={content.imageAlt} | |
| priority | |
| /> | |
| </motion.div> | |
| </div> | |
| ))} |
🤖 Prompt for AI Agents
In
src/app/(home)/_components/ServiceIntroBottomSheet/ServiceIntroBottomSheet.tsx
lines 79 to 118, the current use of a Fragment as a direct child of the Slider
component and placing AnimatePresence inside the map causes animation and slider
functionality issues. To fix this, replace the Fragment with a single wrapper
element that has a unique key for each content item, and move AnimatePresence
outside the map so it wraps the entire list of slides. This ensures proper
animation context and slider behavior.
| export const storyItem = style({ | ||
| flexShrink: 0, | ||
| padding: "0.3rem", | ||
| background: | ||
| "linear-gradient(45deg, #ff6f0f, #ff9047, #ffb07f, rgba(0, 255, 128, 0.7), #49e57d)", | ||
| borderRadius: radius.circle, | ||
| }); |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
스토리 아이템 구조 개선이 잘 되었으나 그라디언트 색상을 검토해 주세요.
CSS 구조를 분리하여 관심사를 명확히 구분한 것은 좋은 개선입니다. 하지만 그라디언트에서 오렌지/빨간색 톤과 녹색 톤을 함께 사용하는 것이 디자인 시스템과 일관성이 있는지 확인이 필요합니다.
다음 스크립트로 디자인 시스템의 색상 팔레트와 일관성을 확인해 주세요:
🏁 Script executed:
#!/bin/bash
# 디자인 시스템 색상 정의 확인
rg -A 10 -B 5 "colors.*=" src/styles/Length of output: 637
다음 스크립트로 그라디언트에 사용된 각 헥스 값이 src/styles/colors.css.ts에 정의되어 있는지 확인해 주세요:
🏁 Script executed:
#!/bin/bash
for hex in ff6f0f ff9047 ffb07f 49e57d 00ff80; do
echo -n "$hex: "
rg -n "$hex" src/styles/colors.css.ts || echo "not found"
doneLength of output: 729
스토리 아이템 그라디언트 색상 팔레트 일관성 확인 및 수정 필요
구조 개선 사항은 승인하나, 현재 하드코딩된 그라디언트 색상들이 디자인 시스템에 정의되어 있지 않아 일관성 문제가 발생합니다. 아래 항목을 검토하고 조치해주세요.
• 문제 위치
- 파일: src/app/(home)/_components/Story/StoryList/StoryList.css.ts
- style 정의:
export const storyItem = style({ /* … */ background: "linear-gradient(45deg, #ff6f0f, #ff9047, #ffb07f, rgba(0, 255, 128, 0.7), #49e57d)", /* … */ });
• 미정의 컬러
- #ff6f0f
- #ff9047
- #ffb07f
- rgba(0, 255, 128, 0.7)
- #49e57d
조치 제안
- 디자인 시스템(src/styles/colors.css.ts)에 해당 색상을 컬러 토큰으로 추가 후 사용
- 혹은 기존 정의된 토큰으로 유사한 색상을 매핑하여 사용
🤖 Prompt for AI Agents
In src/app/(home)/_components/Story/StoryList/StoryList.css.ts lines 5 to 11,
the linear-gradient background uses hardcoded colors not defined in the design
system, causing inconsistency. To fix this, either add these specific colors as
new color tokens in the design system file src/styles/colors.css.ts and then
reference those tokens here, or find existing similar color tokens in the design
system and replace the hardcoded colors with those tokens in the gradient
definition.
✅ 이슈 번호
close #124
🪄 작업 내용 (변경 사항)
📸 스크린샷
로그인 페이지 배경 이미지 UI 수정
webp 확장자 이미지가 캐시되지 않거나, Content unavailable 오류로 인해 로딩에 실패하는 문제가 있었습니다.배경 이미지를
.png로 변경하고, CSS backgroundImage가 아닌<Image /> 컴포넌트로 수정하여 이슈를 해결했습니다!온보딩 스와이프 인터랙션 구현
default.mov
스토리 추가(+) 아이콘 크기 확대
가게 검색시 2초간 빈 화면 수정
default.mov
default.mov
isTyping상태를 추가하여, 사용자가 타이핑을 시작하는 순간부터 스켈레톤 UI가 즉시 노출되도록 처리했습니다.가게 검색 바텀시트 – 서울시 음식점 제공 디스크립션 추가
BottomSheet컴포넌트helperText에 아이콘이 들어가는 경우도 있어서, 타입을 아래와 같이 확장했습니다.스토리 등록 – 가게 검색과 디스크립션 위치 변경
스토리 상세조회 – 디스크립션 클릭 전에도 그라데이션 처리
스토리 그라데이션 테두리 (조회 여부 X)
모바일 바텀시트 확대 이슈 수정
default.mov
default.mov
SearchStoreBottomSheet에autoFocus가 걸려져 있어서 해제하고 테스트해봤는데 잘 되는 것을 확인했습니다!💡 설명
🗣️ 리뷰어에게 전달 사항
📍 트러블 슈팅
Summary by CodeRabbit
신규 기능
개선 및 변경
버그 수정 및 기타