Skip to content

Feat(design-system): InfoBox 컴포넌트 #60

Merged
jllee000 merged 6 commits intodevelopfrom
feat/#59/InfoBox-component
Sep 7, 2025
Merged

Feat(design-system): InfoBox 컴포넌트 #60
jllee000 merged 6 commits intodevelopfrom
feat/#59/InfoBox-component

Conversation

@jllee000
Copy link
Collaborator

@jllee000 jllee000 commented Sep 6, 2025

📌 Related Issues

관련된 Issue를 태그해주세요. (e.g. - close #25)

📄 Tasks

  1. 레이아웃 및 ui 작업
  2. 말줄임 적용

⭐ PR Point (To Reviewer)

180px 영역 넘어가는 타이틀 길이 일시, truncate로 자동 말줄임 ... 적용

📷 Screenshot

image

Summary by CodeRabbit

  • 신기능
    • InfoBox 컴포넌트를 추가했습니다. 선택적 이미지와 함께 제목·출처를 가로형 카드로 표시하며, 긴 제목은 줄임표로 처리됩니다. 디자인 시스템의 공개 API에 포함되어 앱 전반에서 재사용할 수 있습니다.
  • 문서
    • InfoBox용 Storybook 스토리를 추가했습니다. 기본 사례와 긴 제목 사례를 제공하며, 제목·출처·이미지 URL을 컨트롤로 조정해 다양한 상태를 미리볼 수 있습니다.

@coderabbitai
Copy link

coderabbitai bot commented Sep 6, 2025

Walkthrough

디자인 시스템에 InfoBox 컴포넌트를 추가하고, components/index.ts에서 공개(named) export로 노출했습니다. 해당 컴포넌트의 스토리북 스토리(기본/긴 제목 케이스)도 함께 추가되었습니다.

Changes

Cohort / File(s) Summary
Public API Export
packages/design-system/src/components/index.ts
InfoBox./infobox/InfoBox의 default를 named export로 재노출하여 공개 API 확장
New Component
packages/design-system/src/components/infobox/InfoBox.tsx
InfoBox 컴포넌트 추가: 제목, 출처, 선택적 이미지 렌더링 및 유틸리티 클래스 스타일 적용
Storybook
packages/design-system/src/components/infobox/InfoBox.stories.tsx
스토리북 메타 및 스토리 2종(Default, LongTitle) 추가, argTypes 정의

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: 단순 렌더링, 외부 상태 없음
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Assessment against linked issues

Objective Addressed Explanation
팝업 infoBox 컴포넌트 구현 (#59)
progress bar 구현 (#25) 프로그레스바 관련 코드 변경 없음

Assessment against linked issues: Out-of-scope changes

(해당 없음)

Possibly related PRs

Suggested labels

🛠️ Feature

Suggested reviewers

  • jjangminii
  • constantly-dev

Poem

토끼는 박스에 정보를 담아, 퐁당!
살짝 긴 제목도 깔끔히 쏙—쏙!
왼쪽엔 그림, 오른쪽엔 출처와 말.
딱 맞는 카드에 마음이 팔짝!
오늘도 디자인, 점프 업! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#59/InfoBox-component

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.

@jllee000 jllee000 requested a review from jjangminii September 6, 2025 16:36
@github-actions github-actions bot added the feat 기능 개발하라 개발 달려라 달려 label Sep 6, 2025
@jllee000 jllee000 changed the title Fea(design-system): InfoBox 컴포넌트 Feat(design-system): InfoBox 컴포넌트 Sep 6, 2025
@github-actions
Copy link

github-actions bot commented Sep 6, 2025

✅ Storybook chromatic 배포 확인:
🐿️ storybook

Copy link
Collaborator

@jjangminii jjangminii left a comment

Choose a reason for hiding this comment

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

고생하셨습니다-! 스토리북으로 ui 확인해보고 싶었는데 저만 무한 로딩인걸까요...

interface InfoBoxProps {
title: string;
source: string;
imgUrl?: string;
Copy link
Collaborator

Choose a reason for hiding this comment

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

imgUrl이 필수라고 생각이 드는데 혹시 선택으로 두신 이유가 있으신가요?? 혹은 이미지가 없다면 따로 나타나는 아이콘이 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

아 요건 썸네일이 비어있거나 안넘겨줄 시에, 기본 default 이미지로 보여야 하는 경우를 대비해서 선택사항으로 설정해두긴 했습니다!

Copy link
Member

@constantly-dev constantly-dev left a comment

Choose a reason for hiding this comment

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

수고하셨습니다~~ 👍

}
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]">
Copy link
Member

Choose a reason for hiding this comment

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

border-radius는 px로 지정합시다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

헉스바리! 네!

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} />
Copy link
Member

Choose a reason for hiding this comment

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

접근성을 위해 img태그에 alt 속성 추가!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

넹! 추가해두었습니다!

Copy link

@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

♻️ 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-start

Tailwind 표준에는 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

📥 Commits

Reviewing files that changed from the base of the PR and between 16afe23 and 631dc41.

📒 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';

Comment on lines +6 to +16
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>
);
};
Copy link

Choose a reason for hiding this comment

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 기능 개발하라 개발 달려라 달려

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] 팝업 infoBox 컴포넌트 구현

3 participants