Conversation
Walkthrough디자인 시스템에 InfoBox 컴포넌트를 추가하고, components/index.ts에서 공개(named) export로 노출했습니다. 해당 컴포넌트의 스토리북 스토리(기본/긴 제목 케이스)도 함께 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
actor App as Consumer App
participant DS as Design System
participant Info as InfoBox Component
participant DOM as Browser DOM
App->>DS: import { InfoBox }
App->>Info: <InfoBox title, source, imgUrl?>
Info->>DOM: Render image (optional)
Info->>DOM: Render title (truncate) and source
Note over Info,DOM: 단순 렌더링, 외부 상태 없음
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes(해당 없음) Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ 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. Comment |
|
✅ Storybook chromatic 배포 확인: |
jjangminii
left a comment
There was a problem hiding this comment.
고생하셨습니다-! 스토리북으로 ui 확인해보고 싶었는데 저만 무한 로딩인걸까요...
| interface InfoBoxProps { | ||
| title: string; | ||
| source: string; | ||
| imgUrl?: string; |
There was a problem hiding this comment.
imgUrl이 필수라고 생각이 드는데 혹시 선택으로 두신 이유가 있으신가요?? 혹은 이미지가 없다면 따로 나타나는 아이콘이 있을까요?
There was a problem hiding this comment.
아 요건 썸네일이 비어있거나 안넘겨줄 시에, 기본 default 이미지로 보여야 하는 경우를 대비해서 선택사항으로 설정해두긴 했습니다!
| } | ||
| const InfoBox = ({ title, source, imgUrl }: InfoBoxProps) => { | ||
| return ( | ||
| <div className="border-main400 flex h-[6.8rem] w-[24.8rem] items-center justify-between gap-[0.8rem] rounded-[0.4rem] border bg-white px-[0.8rem] py-[1.2rem]"> |
There was a problem hiding this comment.
border-radius는 px로 지정합시다!
| const InfoBox = ({ title, source, imgUrl }: InfoBoxProps) => { | ||
| return ( | ||
| <div className="border-main400 flex h-[6.8rem] w-[24.8rem] items-center justify-between gap-[0.8rem] rounded-[0.4rem] border bg-white px-[0.8rem] py-[1.2rem]"> | ||
| <img className="h-[4.4rem] w-[4.4rem] rounded-[0.4rem]" src={imgUrl} /> |
There was a problem hiding this comment.
접근성을 위해 img태그에 alt 속성 추가!
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/design-system/src/components/infobox/InfoBox.tsx (1)
9-9: img 태그에 alt 누락 (접근성 이슈)alt가 빠져 있습니다. 지난 코멘트와 동일 이슈로 보입니다. 지연 로딩도 같이 붙이면 이점이 큽니다.
- <img className="h-[4.4rem] w-[4.4rem] rounded-[0.4rem]" src={imgUrl} /> + <img + className="h-[4.4rem] w-[4.4rem] rounded-[0.4rem]" + src={imgUrl} + alt={imgAlt ?? `${source} 썸네일`} + loading="lazy" + decoding="async" + />
🧹 Nitpick comments (7)
packages/design-system/src/components/index.ts (1)
16-16: InfoBox 공개 export 추가 LGTM + 타입 export 제안배럴에 기본 export 연결은 적절합니다. 소비자가 prop 타입도 함께 사용할 수 있도록 타입 export도 노출 부탁드립니다.
export { default as InfoBox } from './infobox/InfoBox'; +export type { InfoBoxProps } from './infobox/InfoBox';packages/design-system/src/components/infobox/InfoBox.tsx (3)
1-6: Props 타입 export 및 imgAlt 추가 제안디자인 시스템 소비자가 타입을 가져다 쓰기 쉽도록
InfoBoxProps를 export하고, 접근성/테스트를 위해imgAlt옵션을 제공하면 좋겠습니다.-interface InfoBoxProps { +export interface InfoBoxProps { title: string; source: string; imgUrl?: string; + imgAlt?: string; } -const InfoBox = ({ title, source, imgUrl }: InfoBoxProps) => { +const InfoBox = ({ title, source, imgUrl, imgAlt }: InfoBoxProps) => {
10-10: Tailwind 클래스 오타 의심: items-left → items-startTailwind 표준에는
items-left가 없습니다. 수직 정렬 의도라면items-start로 교체가 맞습니다.- <div className="items-left flex flex-col justify-center gap-[0.2rem] text-left"> + <div className="items-start flex flex-col justify-center gap-[0.2rem] text-left">
11-12: 텍스트 접근성/오버플로 개선 (title tooltip, source truncate)
- 긴 제목은 hover 시 전체를 볼 수 있도록
title속성 추가 권장.source도 예외적으로 길 수 있어 한 줄 말줄임을 권장.- <p className="sub3-sb w-[180px] truncate">{title}</p> - <p className="caption2-m text-font-gray-3">{source}</p> + <p className="sub3-sb w-[180px] truncate" title={title}>{title}</p> + <p className="caption2-m text-font-gray-3 truncate">{source}</p>packages/design-system/src/components/infobox/InfoBox.stories.tsx (3)
11-24: argTypes control 표기 통일 (마이그레이션 호환성)
control: 'text'대신 객체 형태가 권장됩니다.- title: { - control: 'text', + title: { + control: { type: 'text' }, description: '메인 제목 (180px 넘어가면 … 처리)', }, - source: { - control: 'text', + source: { + control: { type: 'text' }, description: '출처 (예: 블로그, 뉴스 등)', }, - imgUrl: { - control: 'text', + imgUrl: { + control: { type: 'text' }, description: '썸네일 이미지 URL', },
31-38: 스토리 args에 imgAlt 추가 + 외부 이미지 의존도 완화 제안컴포넌트 a11y 개선에 맞춰
imgAlt도 함께 제공해 주세요. 또한 예시 이미지는 외부 저작권/가용성 이슈가 적은 플레이스홀더로 교체 권장입니다.export const Default: Story = { args: { - imgUrl: - 'https://previews.123rf.com/images/latkun/latkun1712/latkun171200130/92172856-empty-transparent-background-seamless-pattern.jpg', + imgUrl: 'https://placehold.co/88x88', + imgAlt: '네이버 블로그 썸네일', title: '집에서 할 수 있는 것들은 무엇이 있을까요구르트', source: '네이버 블로그', }, };
40-48: 빈 이미지 케이스 스토리 추가 권장플레이스홀더/누락 처리 로직이 의도대로 동작하는지 검증용 스토리를 하나 더 두면 안정적입니다. 또한 LongTitle에도
imgAlt를 제공해 주세요.export const LongTitle: Story = { args: { - imgUrl: - 'https://previews.123rf.com/images/latkun/latkun1712/latkun171200130/92172856-empty-transparent-background-seamless-pattern.jpg', + imgUrl: 'https://placehold.co/88x88', + imgAlt: '브런치 썸네일', title: '이건 엄청엄청엄청 길어서 180px 넘어가면 자동으로 ... 처리되는 긴 제목 테스트용 텍스트입니다', source: '브런치', }, }; + +export const NoImage: Story = { + args: { + title: '이미지 없이도 자연스럽게 렌더링되는지 확인', + source: '핀백 팀', + }, +};
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/design-system/src/components/index.ts(1 hunks)packages/design-system/src/components/infobox/InfoBox.stories.tsx(1 hunks)packages/design-system/src/components/infobox/InfoBox.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: constantly-dev
PR: Pinback-Team/pinback-client#30
File: apps/extension/src/App.tsx:10-21
Timestamp: 2025-07-08T11:47:10.642Z
Learning: In apps/extension/src/App.tsx, the InfoBox component currently uses a hardcoded external URL for the icon prop as a temporary static placeholder. The plan is to replace this with dynamic favicon extraction from bookmarked websites in future iterations.
📚 Learning: 2025-07-15T20:00:13.756Z
Learnt from: constantly-dev
PR: Pinback-Team/pinback-client#80
File: apps/client/src/shared/components/ui/modalPop/ModalPop.tsx:36-41
Timestamp: 2025-07-15T20:00:13.756Z
Learning: In apps/client/src/shared/components/ui/modalPop/ModalPop.tsx, the InfoBox component uses hardcoded values for title, location, and icon URL as temporary test data. These should be replaced with dynamic data from props when implementing actual functionality and should be marked with TODO comments for future changes.
Applied to files:
packages/design-system/src/components/infobox/InfoBox.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: storybook
🔇 Additional comments (1)
packages/design-system/src/components/infobox/InfoBox.stories.tsx (1)
1-1: Storybook 타입 import 경로 확인 요청프로젝트 설정에 따라 권장 경로는
@storybook/react입니다. 현재@storybook/react-vite를 쓰고 있어 타입 해석 이슈가 없는지 확인해 주세요.-import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from '@storybook/react';
| const InfoBox = ({ title, source, imgUrl }: InfoBoxProps) => { | ||
| return ( | ||
| <div className="border-main400 flex h-[6.8rem] w-[24.8rem] items-center justify-between gap-[0.8rem] rounded-[4px] border bg-white px-[0.8rem] py-[1.2rem]"> | ||
| <img className="h-[4.4rem] w-[4.4rem] rounded-[0.4rem]" src={imgUrl} /> | ||
| <div className="items-left flex flex-col justify-center gap-[0.2rem] text-left"> | ||
| <p className="sub3-sb w-[180px] truncate">{title}</p> | ||
| <p className="caption2-m text-font-gray-3">{source}</p> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
imgUrl 미지정/로딩 실패 시 처리 보완
imgUrl이 선택 prop인데도 항상 img를 렌더링합니다. 비어있을 때는 플레이스홀더로 대체하거나 렌더링을 생략해 레이아웃 깨짐을 방지하는 편이 안전합니다.
- return (
+ return (
<div className="border-main400 flex h-[6.8rem] w-[24.8rem] items-center justify-between gap-[0.8rem] rounded-[4px] border bg-white px-[0.8rem] py-[1.2rem]">
- <img className="h-[4.4rem] w-[4.4rem] rounded-[0.4rem]" src={imgUrl} />
+ {imgUrl ? (
+ <img
+ className="h-[4.4rem] w-[4.4rem] rounded-[0.4rem]"
+ src={imgUrl}
+ alt={imgAlt ?? `${source} 썸네일`}
+ loading="lazy"
+ decoding="async"
+ />
+ ) : (
+ <div
+ className="h-[4.4rem] w-[4.4rem] rounded-[0.4rem] bg-gray-100"
+ aria-hidden="true"
+ />
+ )}
<div className="items-left flex flex-col justify-center gap-[0.2rem] text-left">
<p className="sub3-sb w-[180px] truncate">{title}</p>
<p className="caption2-m text-font-gray-3">{source}</p>
</div>
</div>
);원하시면 디자인 토큰에 맞는 플레이스홀더(아이콘/이미지)도 함께 제안드릴게요.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/design-system/src/components/infobox/InfoBox.tsx around lines 6 to
16, the component always renders an <img> even when the optional imgUrl is
missing or fails to load; update the component to conditionally render the image
only if imgUrl is truthy, add an onError handler to swap to a placeholder state
when loading fails, and ensure the image includes an appropriate alt text; when
imgUrl is absent or error occurs render a placeholder element (same dimensions
and border-radius as the image, using a background color or icon from design
tokens) to preserve layout and accessibility.
📌 Related Issues
📄 Tasks
⭐ PR Point (To Reviewer)
180px 영역 넘어가는 타이틀 길이 일시, truncate로 자동 말줄임 ... 적용
📷 Screenshot
Summary by CodeRabbit