[SRLT-142] 랜딩페이지 반응형 수정#119
Hidden character warning
Conversation
Walkthrough모바일 알림 상태 관리가 단순 부울에서 표현력 있는 타입('business', 'price', null)으로 리팩토링되었습니다. 또한 배경 표시 옵션이 추가되고, useCountdown 훅의 SSR 처리가 마운트 플래그를 통해 최적화되었습니다. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/app/_components/common/MobileNavAlertModal.tsx`:
- Around line 19-36: The two decorative <Image> usages in the
MobileNavAlertModal component are currently given descriptive alt text which
makes screen readers announce irrelevant content; change both images to be
purely decorative by setting alt="" and adding aria-hidden="true" (or otherwise
marking them decorative via CSS background if you prefer), e.g., update the
Image elements rendered in MobileNavAlertModal to use alt="" and
aria-hidden="true" so assistive tech ignores them.
In `@src/hooks/useCountdown.ts`:
- Around line 20-24: The hook currently initializes timeLeft to initialTimeLeft
which renders "0d 0h 0m 0s" on SSR/hydration and looks expired; change
useCountdown so it doesn't expose the zero state before the component mounts:
keep mounted state (mounted) and set it true inside a useEffect, and either (A)
return a second value like isMounted (or null/undefined timeLeft) so callers can
render a hidden/sized placeholder before mount, or (B) have the hook itself
return a placeholder object (same layout size) until mounted; update references
to initialTimeLeft, useCountdown, timeLeft and mounted accordingly and apply the
same change at the other occurrence noted (line ~38) so no zero countdown is
rendered pre-mount.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 085d78c1-e43e-4a7c-a36b-1a7bd100c59d
⛔ Files ignored due to path filters (8)
public/images/bussiness_mobile.pngis excluded by!**/*.pngpublic/images/bussiness_tablet.pngis excluded by!**/*.pngpublic/images/landing/landing_expert1.pngis excluded by!**/*.pngpublic/images/landing/landing_expert1_mobile.pngis excluded by!**/*.pngpublic/images/landing/landing_expert2.pngis excluded by!**/*.pngpublic/images/landing/landing_expert2_mobile.pngis excluded by!**/*.pngpublic/images/landing/landing_expert3.pngis excluded by!**/*.pngpublic/images/landing/landing_expert3_mobile.pngis excluded by!**/*.png
📒 Files selected for processing (6)
src/app/_components/common/Header.tsxsrc/app/_components/common/MobileNavAlertModal.tsxsrc/app/_components/landing/Landing.tsxsrc/app/_components/landing/LandingChecklist.tsxsrc/app/_components/landing/LandingPaySection.tsxsrc/hooks/useCountdown.ts
| <Image | ||
| src="/images/bussiness_mobile.png" | ||
| alt="사업계획서 배경" | ||
| fill | ||
| className="object-cover md:hidden" | ||
| quality={100} | ||
| unoptimized | ||
| priority | ||
| /> | ||
| <Image | ||
| src="/images/bussiness_tablet.png" | ||
| alt="사업계획서 배경" | ||
| fill | ||
| className="hidden object-cover md:block" | ||
| quality={100} | ||
| unoptimized | ||
| priority | ||
| /> |
There was a problem hiding this comment.
배경 이미지는 장식용으로 처리해주세요.
이 이미지는 정보 전달 역할이 아니라 시각적 배경이라서, 지금처럼 alt 텍스트를 두면 스크린리더가 불필요한 설명을 읽게 됩니다. alt=""로 비우고 aria-hidden을 주거나 CSS background로 옮기는 편이 접근성에 맞습니다.
♿ 제안 수정안
<Image
src="/images/bussiness_mobile.png"
- alt="사업계획서 배경"
+ alt=""
+ aria-hidden="true"
fill
className="object-cover md:hidden"
quality={100}
unoptimized
priority
/>
<Image
src="/images/bussiness_tablet.png"
- alt="사업계획서 배경"
+ alt=""
+ aria-hidden="true"
fill
className="hidden object-cover md:block"
quality={100}
unoptimized
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/bussiness_mobile.png" | |
| alt="사업계획서 배경" | |
| fill | |
| className="object-cover md:hidden" | |
| quality={100} | |
| unoptimized | |
| priority | |
| /> | |
| <Image | |
| src="/images/bussiness_tablet.png" | |
| alt="사업계획서 배경" | |
| fill | |
| className="hidden object-cover md:block" | |
| quality={100} | |
| unoptimized | |
| priority | |
| /> | |
| <Image | |
| src="/images/bussiness_mobile.png" | |
| alt="" | |
| aria-hidden="true" | |
| fill | |
| className="object-cover md:hidden" | |
| quality={100} | |
| unoptimized | |
| priority | |
| /> | |
| <Image | |
| src="/images/bussiness_tablet.png" | |
| alt="" | |
| aria-hidden="true" | |
| fill | |
| className="hidden object-cover md:block" | |
| quality={100} | |
| unoptimized | |
| priority | |
| /> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/app/_components/common/MobileNavAlertModal.tsx` around lines 19 - 36, The
two decorative <Image> usages in the MobileNavAlertModal component are currently
given descriptive alt text which makes screen readers announce irrelevant
content; change both images to be purely decorative by setting alt="" and adding
aria-hidden="true" (or otherwise marking them decorative via CSS background if
you prefer), e.g., update the Image elements rendered in MobileNavAlertModal to
use alt="" and aria-hidden="true" so assistive tech ignores them.
| const initialTimeLeft = { days: 0, hours: 0, minutes: 0, seconds: 0 }; | ||
|
|
||
| export const useCountdown = (targetDate: string) => { | ||
| const [timeLeft, setTimeLeft] = useState(() => calculateTimeLeft(targetDate)); | ||
| const [timeLeft, setTimeLeft] = useState(initialTimeLeft); | ||
| const [mounted, setMounted] = useState(false); |
There was a problem hiding this comment.
초기 0 반환 때문에 카운트다운이 잠깐 만료된 것처럼 보입니다.
지금 구현은 SSR/초기 hydration에서 항상 0일 0시간 0분 0초를 먼저 그린 뒤 effect에서 실제 값으로 바뀝니다. hydration 에러는 피했지만, 랜딩 배너가 잠깐 종료된 것처럼 보여 첫 인상이 깨집니다. mount 전에는 값을 숨기거나 동일 크기 placeholder를 렌더링하도록 분리하는 편이 안전합니다.
Also applies to: 38-38
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/hooks/useCountdown.ts` around lines 20 - 24, The hook currently
initializes timeLeft to initialTimeLeft which renders "0d 0h 0m 0s" on
SSR/hydration and looks expired; change useCountdown so it doesn't expose the
zero state before the component mounts: keep mounted state (mounted) and set it
true inside a useEffect, and either (A) return a second value like isMounted (or
null/undefined timeLeft) so callers can render a hidden/sized placeholder before
mount, or (B) have the hook itself return a placeholder object (same layout
size) until mounted; update references to initialTimeLeft, useCountdown,
timeLeft and mounted accordingly and apply the same change at the other
occurrence noted (line ~38) so no zero countdown is rendered pre-mount.
#️⃣ 관련 이슈
✍️ 작업 내용 요약
💡 작업 내용
기능
🖥️ 구현 화면
기타 사항
Summary by CodeRabbit
릴리스 노트
새로운 기능
개선사항