Skip to content

sp1 1차 QA 반영 (대시보드-UI관련)#112

Merged
constantly-dev merged 7 commits intodevelopfrom
fix/#108/sp1-qa-dashboard
Sep 17, 2025
Merged

sp1 1차 QA 반영 (대시보드-UI관련)#112
constantly-dev merged 7 commits intodevelopfrom
fix/#108/sp1-qa-dashboard

Conversation

@constantly-dev
Copy link
Member

@constantly-dev constantly-dev commented Sep 17, 2025

📌 Related Issues

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

📄 Tasks

  • card layout padding right 추가
  • card 고정 height 추가
  • remind/myBookmark no articles state 추가
  • sidebar logo padding left 추가
  • sideitem cursor pointer 추가
    ETC. 사소한 리팩토링

Summary by CodeRabbit

  • New Features
    • 북마크/리마인드 빈 화면을 상황별로 구분해 안내(전체 없음, 읽지 않음 없음, 리마인드 없음)합니다.
  • 동작 변경
    • 리마인드 페이지에 로딩 표시를 추가했습니다.
    • 사이드바에서 리마인드/북마크/레벨 이동 시 선택한 카테고리가 유지됩니다.
  • Style
    • 옵션 메뉴 버튼 텍스트를 좌측 정렬하고, 사이드바/페이지 여백을 조정했습니다.
    • 카드 높이 설정이 유연해졌으며, 일부 카드에 고정 높이를 적용했습니다.
    • 사이드 아이템에 포인터 커서를 추가했습니다.

@vercel
Copy link

vercel bot commented Sep 17, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
pinback-client-client Ready Ready Preview Comment Sep 17, 2025 5:34am

@coderabbitai
Copy link

coderabbitai bot commented Sep 17, 2025

Walkthrough

빈 상태 처리 로직을 세분화하고 관련 컴포넌트를 추가/수정했으며, 카드 베이스 컴포넌트에 className 전달을 허용하도록 API를 확장했습니다. 북마크/리마인드 페이지의 레이아웃 여백과 목록 래퍼 스타일을 조정했고, 사이드바 및 옵션 메뉴 버튼의 스타일/동작을 미세 조정했습니다.

Changes

Cohort / File(s) Summary
MyBookmark 빈 상태 세분화
apps/client/src/pages/myBookmark/MyBookmark.tsx, apps/client/src/pages/myBookmark/components/noUnreadArticles/NoUnreadArticles.tsx
전체 글 수가 0일 때와 필터 결과가 0일 때를 분리하여 NoArticles vs NoUnreadArticles 조건 렌더링. 레이아웃 우측 패딩 추가, 그리드 max-width 제거. NoUnreadArticles 컴포넌트 신규 추가.
Remind 빈/로딩 상태 및 카피
apps/client/src/pages/remind/Remind.tsx, apps/client/src/pages/remind/components/noReadArticles/NoReadArticles.tsx, apps/client/src/pages/remind/components/noRemindArticles/NoRemindArticles.tsx
isPending 로딩 분기 추가. 읽음/안읽음/전체 0 여부에 따라 NoRemindArticles/NoReadArticles/NoUnreadArticles를 조건 렌더링. 레이아웃 우측 패딩 및 래퍼 스타일 조정. NoReadArticles 문구 업데이트. NoRemindArticles 신규 추가.
사이드바 미세 조정
apps/client/src/shared/components/sidebar/Sidebar.tsx, apps/client/src/shared/components/sidebar/SideItem.tsx
헤더 좌우 패딩 및 로고 포인터 커서 추가. 특정 onClick에서 setSelectedCategoryId(null) 호출 제거로 카테고리 선택 상태 유지. SideItem에 cursor-pointer 추가.
옵션 메뉴 버튼 정렬 조정
apps/client/src/shared/components/optionsMenuButton/OptionsMenuButton.tsx
항목 스타일에서 justify-center 제거, pl-[0.8rem] 추가로 좌측 정렬화.
디자인 시스템 카드 API/스타일
packages/design-system/src/components/card/BaseCard.tsx, .../card/MyBookmarkCard.tsx, .../card/RemindCard.tsx
BaseCard에 className prop 추가 및 고정 높이 제거. 소비처(MyBookmarkCard, RemindCard)에서 개별 높이 클래스 전달(h-[33.8rem], h-[35.6rem]). cn 유틸로 클래스 병합.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor User
participant MyBookmark as MyBookmark Page
participant Store as Data (total, filtered)
participant UI as Empty State

User->>MyBookmark: 페이지 진입
MyBookmark->>Store: totalArticle, filteredArticles 조회
Store-->>MyBookmark: { total, filteredCount }
alt filteredCount == 0
  alt total == 0
    MyBookmark->>UI: 렌더 NoArticles
  else total > 0
    MyBookmark->>UI: 렌더 NoUnreadArticles
  end
else filteredCount > 0
  MyBookmark->>UI: 기사 목록 렌더
end
Loading
sequenceDiagram
autonumber
actor User
participant Remind as Remind Page
participant Hook as useGetRemindArticles
participant UI as Empty State

User->>Remind: 페이지 진입
Remind->>Hook: 데이터 요청
alt isPending
  Hook-->>Remind: isPending = true
  Remind->>User: "Loading..."
else 완료
  Hook-->>Remind: { readCount, unreadCount, activeBadge }
  alt readCount == 0 and unreadCount == 0
    Remind->>UI: 렌더 NoRemindArticles
  else activeBadge == "읽음"
    Remind->>UI: 조건 NoReadArticles (필터 결과 0일 때)
  else activeBadge == "안 읽음"
    Remind->>UI: 조건 NoUnreadArticles (필터 결과 0일 때)
  end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

🛠️ Feature, feat

Suggested reviewers

  • jllee000
  • jjangminii

Poem

꼬물꼬물 코드밭, 도토리 찾는 날—
빈 손일 땐 살짝, 치삐가 “앗..” 하고 말 🙂
읽을 것도, 안 읽을 것도 갈래를 나눠-
카드의 키가 쑥쑥, 옷은 className으로!
사이드바 톡—선택은 그대로, 길만 환해졌지 🐇🌰

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/#108/sp1-qa-dashboard

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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.

Pre-merge checks

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning 본 PR은 [#108]의 SP1 QA 항목들(카드 우측 패딩, 카드 고정 높이 추가, remind/myBookmark의 빈 상태 컴포넌트 추가, 사이드바 로고 패딩·SideItem 포인터 등)을 코드 변경으로 충족하지만, [#25]에 명시된 design-system Progress 컴포넌트 구현(컴포넌트 추가·접근성 속성·스토리북 및 인터랙션 테스트·@radix-ui/react-progress 의존성 등)은 PR에 포함되어 있지 않습니다. 해결안: #25 관련 작업을 본 PR에서 반드시 포함해야 한다면 Progress 컴포넌트 구현·스토리북·테스트·의존성 변경을 추가하고 재검토를 요청하거나, 해당 작업을 별도 PR로 분리해 이 PR은 #108 QA 변경만 닫도록 정리해 주세요.
Out of Scope Changes Check ⚠️ Warning 대부분 변경은 #108 QA 범위에 해당하지만 일부 변경은 PR 설명의 명시된 작업 목록을 벗어납니다; 특히 Sidebar에서 setSelectedCategoryId(null) 호출 제거로 내비게이션 동작이 변경된 점과 OptionsMenuButton의 정렬(justify 제거·왼쪽 패딩 추가)은 명시된 작업에 없던 동작/레이아웃 변경입니다. 또한 packages/design-system의 BaseCard에 className prop을 추가한 것은 카드 고정 높이 목적과 관련되지만 공개 API 변경이므로 소비자 영향(마이그레이션 필요성)을 고려해야 합니다. 권고: 동작 변경(사이드바 카테고리 초기화 제거)과 범용 컴포넌트 API 변경은 별도 커밋 또는 PR로 분리하거나 PR 설명에 변경 이유와 범위를 명확히 기재하고 마이그레이션 안내, 영향받는 소비자 목록·테스트를 함께 제공해 주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed PR 설명은 저장소 템플릿의 핵심 항목을 따르고 있으며 "Related Issues"에 close #108가 명시되어 있고 작업 목록으로 주요 변경사항(카드 패딩·고정 높이·빈 상태 추가·사이드바 등)이 요약되어 있어 전반적으로 완성되어 있습니다. PR Point 및 스크린샷이 없는 것은 템플릿상 선택적 항목이라 주요 정보는 충족합니다.
Title Check ✅ Passed 제목 "sp1 1차 QA 반영 (대시보드-UI관련)"은 PR 목표에 명시된 'SP1 QA 대시보드 1차 반영'과 일치하며 카드 레이아웃·고정 높이 등 대시보드 관련 UI 수정 내용을 간결하게 요약합니다. 문구가 짧고 PR의 주된 목적을 전달하므로 팀원이 히스토리를 빠르게 스캔할 때 적절합니다. 다만 PR에는 사이드바, 북마크/리마인드의 empty-state 등 대시보드 외 UI 변경도 포함되어 있어 범위가 다소 넓게 해석될 수 있습니다.

@github-actions github-actions bot added the fix 버그 수정하라 러브버그 label Sep 17, 2025
@github-actions
Copy link

✅ Storybook chromatic 배포 확인:
🐿️ storybook

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (8)
apps/client/src/shared/components/optionsMenuButton/OptionsMenuButton.tsx (1)

3-8: ref 전달 방식 버그: forwardRef로 전환 필요

함수형 컴포넌트에서 ref는 props로 받을 수 없고, 현재 구현은 항상 undefined가 되어 레퍼런스가 깨집니다. forwardRef로 전환해주세요.

-import { cn } from '@pinback/design-system/utils';
+import { cn } from '@pinback/design-system/utils';
+import { forwardRef } from 'react';
 
-export interface OptionsMenuButtonProps {
-  ref?: React.Ref<HTMLDivElement>;
+export interface OptionsMenuButtonProps extends React.ComponentPropsWithoutRef<'div'> {
   onEdit: () => void;
   onDelete: () => void;
   className?: string;
 }
 
-const ITEM_STYLE =
+const ITEM_STYLE =
   'body4-r text-font-black-1 h-[3.6rem] w-full ' +
   'flex items-center pl-[0.8rem] ' +
   'hover:bg-gray100 focus-visible:bg-gray100 active:bg-gray200 ' +
   'outline-none transition-colors';
 
-export default function OptionsMenuButton({
-  ref,
-  onEdit,
-  onDelete,
-  className,
-}: OptionsMenuButtonProps) {
-  return (
-    <div
-      ref={ref}
+const OptionsMenuButton = forwardRef<HTMLDivElement, OptionsMenuButtonProps>(function OptionsMenuButton(
+  { onEdit, onDelete, className, ...rest },
+  ref
+) {
+  return (
+    <div
+      ref={ref}
       role="menu"
       aria-label="옵션 메뉴"
       className={cn(
         'bg-white-bg common-shadow rounded-[0.4rem] px-0 py-[1.2rem]',
         'flex h-[9.6rem] w-[12.4rem] flex-col items-center justify-center',
         className
       )}
+      {...rest}
     >
       <button type="button" onClick={onEdit} className={ITEM_STYLE}>
         수정하기
       </button>
       <button type="button" onClick={onDelete} className={ITEM_STYLE}>
         삭제하기
       </button>
     </div>
   );
-}
+});
+
+export default OptionsMenuButton;

Also applies to: 16-21, 23-33

apps/client/src/pages/myBookmark/MyBookmark.tsx (4)

71-72: 런타임 오류: 존재하지 않는 close() 호출

useAnchoredMenu에서 가져온 함수명은 closeMenu인데 close()를 호출하고 있습니다. 즉시 수정 필요.

-        close();
+        closeMenu();

56-58: 카테고리 필터 미적용으로 목록/카운트 불일치

categoryId가 존재해도 목록은 항상 전체/미읽음 쿼리를 사용합니다. 카테고리 전용 쿼리(categoryArticles)를 적용하세요.

-  const articlesToDisplay =
-    activeBadge === 'all' ? articles?.articles : unreadArticles?.articles;
+  const listSource = categoryId
+    ? categoryArticles
+    : activeBadge === 'all'
+      ? articles
+      : unreadArticles;
+  const articlesToDisplay = listSource?.articles;

동일 맥락으로 배지 카운트도 아래 코멘트 패치를 참고하세요.


114-117: 배지 카운트도 카테고리 컨텍스트 반영 필요

카테고리 선택 시 카운트가 전체 기준으로 표시됩니다.

-          countNum={articles?.totalArticle || 0}
+          countNum={(categoryId ? categoryArticles?.totalArticle : articles?.totalArticle) || 0}
...
-          countNum={articles?.totalUnreadArticle || 0}
+          countNum={(categoryId ? categoryArticles?.totalUnreadArticle : articles?.totalUnreadArticle) || 0}

Also applies to: 119-123


136-138: 새 탭 오픈 시 reverse‑tabnabbing 방지

window.open에 noopener,noreferrer 특성을 추가하세요.

-                window.open(article.url, '_blank');
+                window.open(article.url, '_blank', 'noopener,noreferrer');
apps/client/src/pages/remind/Remind.tsx (3)

52-54: 런타임 오류: 존재하지 않는 close() 호출

여기서도 closeMenu가 아닌 close()를 호출하고 있습니다. 즉시 수정 필요.

-        queryClient.invalidateQueries({ queryKey: ['remindArticles'] });
-        close();
+        queryClient.invalidateQueries({ queryKey: ['remindArticles'] });
+        closeMenu();

111-112: reverse‑tabnabbing 방지

새 탭 오픈 시 보안 특성 추가 필요.

-              onClick={() => {
-                window.open(article.url, '_blank');
+              onClick={() => {
+                window.open(article.url, '_blank', 'noopener,noreferrer');

104-110: Options 메뉴 ID 불일치 — categoryId가 articleId로 사용되고 있습니다 (긴급 수정 필요)
openMenu에 article.category.categoryId를 전달하는 반면, onEdit 핸들러에서 전달된 id로 getArticleDetail(id)를 호출해 categoryId로 아티클 상세를 조회하는 흐름이 확인되었습니다. openMenu에 articleId를 전달하거나(onOptionsClick → openMenu(article.id,...)), 아니면 onEdit에서 id 의미에 따라 분기/매핑하여 getArticleDetail에 올바른 articleId만 전달하도록 수정하세요.
위치: apps/client/src/pages/remind/Remind.tsx (openMenu 호출부 ≈ 104–110, onEdit 핸들러 ≈ 137–141), 참고: apps/client/src/shared/apis/queries.ts (getArticleDetail).

🧹 Nitpick comments (14)
apps/client/src/shared/components/sidebar/SideItem.tsx (1)

34-42: div 클릭 대상의 접근성 보완 필요: role/tabIndex/키보드 핸들링 추가 권장

컨테이너가 div이므로 키보드 접근(Enter/Space)이 불가합니다. 내부에 button이 존재해 부모를 button으로 바꾸기 어렵기 때문에, role="button"과 tabIndex, onKeyDown을 추가하는 쪽을 추천합니다.

-    <div
+    <div
+      role="button"
+      tabIndex={0}
       className={cn(
         'flex h-[4.4rem] items-center gap-[0.8rem] rounded-[0.4rem] px-[0.8rem] py-[1.2rem]',
         'cursor-pointer transition-colors',
         active ? 'bg-main0 text-main600' : 'bg-white-bg text-font-gray-2',
         className
       )}
-      onClick={onClick}
+      onClick={onClick}
+      onKeyDown={(e) => {
+        if (e.key === 'Enter' || e.key === ' ') {
+          e.preventDefault();
+          onClick();
+        }
+      }}
     >
apps/client/src/pages/remind/components/noReadArticles/NoReadArticles.tsx (1)

6-11: 빈 상태 일러스트 alt 텍스트 정리

해당 이미지는 장식적 용도라면 alt를 빈 문자열로 두는 편이 스크린 리더에 적합합니다. (현재 "No Articles"는 불필요한 영문 아나운스가 됩니다.)

-      <img src={chippiNoArticles} alt="No Articles" />
+      <img src={chippiNoArticles} alt="" />
apps/client/src/shared/components/optionsMenuButton/OptionsMenuButton.tsx (1)

25-27: ARIA 메뉴 패턴 불일치: role 사용을 간소화하거나 menuitem 역할 부여

role="menu"를 사용하면 자식에 role="menuitem"과 키보드 네비게이션(↑/↓)이 필요합니다. 구현 부담을 줄이려면 role을 제거(혹은 group)하고 기본 버튼 접근성에 맡기는 것을 권장합니다.

-      role="menu"
-      aria-label="옵션 메뉴"
+      role="group"
+      aria-label="옵션 메뉴"

Also applies to: 33-38

apps/client/src/pages/remind/components/noRemindArticles/NoRemindArticles.tsx (2)

6-11: 장식 이미지 alt 정리

장식적 이미지라면 alt를 빈 문자열로 두어 불필요한 낭독을 막아주세요.

-      <img src={chippiNoArticles} alt="No Articles" />
+      <img src={chippiNoArticles} alt="" />

3-14: EmptyState 패턴 공통화 제안

동일한 레이아웃/타이포 조합의 EmptyState 컴포넌트가 다수 생기고 있습니다. EmptyState({ image, title, description }) 같은 프레젠테이셔널 컴포넌트를 공용으로 추출하면 중복 제거와 카피/스타일 일관성 유지가 용이합니다.

apps/client/src/shared/components/sidebar/Sidebar.tsx (1)

106-112: 로고에 커서 포인터만 있고 클릭 동작 없음 → UX 혼동

cursor-pointer가 추가됐지만 클릭 핸들러가 없어 사용자에게 혼동을 줄 수 있습니다. 로고를 홈/리마인드로 이동시키거나 포인터를 제거하세요.

-        <header className="px-[0.8rem] py-[2.8rem]">
-          <Icon
-            name="logo"
-            aria-label="Pinback 로고"
-            className="h-[2.4rem] w-[8.7rem] cursor-pointer"
-          />
-        </header>
+        <header className="px-[0.8rem] py-[2.8rem]">
+          <button
+            type="button"
+            aria-label="대시보드로 이동"
+            className="cursor-pointer"
+            onClick={() => {
+              closeMenu();
+              goRemind();
+            }}
+          >
+            <Icon name="logo" aria-hidden className="h-[2.4rem] w-[8.7rem]" />
+          </button>
+        </header>
apps/client/src/pages/myBookmark/components/noUnreadArticles/NoUnreadArticles.tsx (2)

6-11: 장식 이미지 alt 정리

장식 목적이면 alt를 빈 문자열로 두세요. 불필요한 영문 아나운스가 제거됩니다.

-      <img src={chippiNoRemindArticles} alt="No Articles" />
+      <img src={chippiNoRemindArticles} alt="" />

3-14: EmptyState 공용 컴포넌트화 제안

NoReadArticles, NoRemindArticles와 동일한 레이아웃입니다. 공통 EmptyState로 추출해 복붙을 줄이고 카피/스타일을 한 곳에서 유지하세요.

packages/design-system/src/components/card/BaseCard.tsx (1)

3-7: DOM 속성 위임/forwardRef 고려

id/aria-* 전달 및 포커스 제어를 위해 ...props/forwardRef를 도입하는 것을 권장합니다.

원하시면 전체 적용 패치도 제공 가능합니다.

Also applies to: 9-9

apps/client/src/pages/myBookmark/MyBookmark.tsx (4)

86-92: 빈 상태 분기 보강: 뷰 컨텍스트 고려

현재는 “모아보기(all)”에서도 항상 NoUnreadArticles가 표시될 수 있습니다. activeBadge·카테고리 기준으로 분기하세요.

-  const EmptyStateComponent = () => {
-    if (articles?.totalArticle === 0) {
-      return <NoArticles />;
-    }
-    return <NoUnreadArticles />;
-  };
+  const EmptyStateComponent = () => {
+    const totalAll =
+      (categoryId ? categoryArticles?.totalArticle : articles?.totalArticle) ?? 0;
+    if (totalAll === 0) return <NoArticles />;
+    return activeBadge === 'notRead' ? <NoUnreadArticles /> : <NoArticles />;
+  };

43-44: 디버그 로그 제거

불필요한 console.log는 제거해주세요.

-  console.log('categoryArticles', categoryArticles);

94-94: 스크롤 컨테이너 구조 정리(내부 h-screen 제거, flex-1 사용)

중첩 h-screen은 이중 스크롤/레이아웃 깨짐을 유발할 수 있습니다.

-    <div className="flex h-screen flex-col py-[5.2rem] pl-[8rem] pr-[5rem]">
+    <div className="flex h-screen flex-col py-[5.2rem] pl-[8rem] pr-[5rem]">
...
-        <div className="scrollbar-hide mt-[2.6rem] flex h-screen flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth">
+        <div className="scrollbar-hide mt-[2.6rem] flex flex-1 flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth">

Also applies to: 127-127


59-77: 쿼리 키 팩토리 도입 권장

문자열 키 오타/중복을 방지하기 위해 queryKey factory로 통합 관리하세요.

원하시면 키 팩토리 초안 제공 가능합니다.

apps/client/src/pages/remind/Remind.tsx (1)

79-80: 스크롤 레이아웃 일관성 확보

MyBookmark와 동일하게 화면 높이 기준 내부 스크롤을 권장합니다.

-    <div className="flex flex-col py-[5.2rem] pl-[8rem] pr-[5rem]">
+    <div className="flex h-screen flex-col py-[5.2rem] pl-[8rem] pr-[5rem]">
...
-        <div className="scrollbar-hide mt-[2.6rem] flex flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth">
+        <div className="scrollbar-hide mt-[2.6rem] flex flex-1 flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth">

Also applies to: 97-98

📜 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 3c8069e and e458ec3.

📒 Files selected for processing (11)
  • apps/client/src/pages/myBookmark/MyBookmark.tsx (4 hunks)
  • apps/client/src/pages/myBookmark/components/noUnreadArticles/NoUnreadArticles.tsx (1 hunks)
  • apps/client/src/pages/remind/Remind.tsx (5 hunks)
  • apps/client/src/pages/remind/components/noReadArticles/NoReadArticles.tsx (1 hunks)
  • apps/client/src/pages/remind/components/noRemindArticles/NoRemindArticles.tsx (1 hunks)
  • apps/client/src/shared/components/optionsMenuButton/OptionsMenuButton.tsx (1 hunks)
  • apps/client/src/shared/components/sidebar/SideItem.tsx (1 hunks)
  • apps/client/src/shared/components/sidebar/Sidebar.tsx (1 hunks)
  • packages/design-system/src/components/card/BaseCard.tsx (1 hunks)
  • packages/design-system/src/components/card/MyBookmarkCard.tsx (1 hunks)
  • packages/design-system/src/components/card/RemindCard.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: constantly-dev
PR: Pinback-Team/pinback-client#2
File: pnpm-workspace.yaml:3-3
Timestamp: 2025-08-18T13:48:59.065Z
Learning: constantly-dev는 docs 디렉터리를 컨벤션 문서 추가용으로 사용할 예정이라고 명시했습니다.
🧬 Code graph analysis (3)
apps/client/src/shared/components/sidebar/Sidebar.tsx (1)
packages/design-system/src/icons/components/icon.tsx (1)
  • Icon (71-114)
packages/design-system/src/components/card/BaseCard.tsx (1)
packages/design-system/src/lib/utils.ts (1)
  • cn (108-110)
apps/client/src/pages/remind/Remind.tsx (1)
apps/client/src/pages/remind/apis/queries.ts (1)
  • useGetRemindArticles (6-16)
⏰ 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 (9)
apps/client/src/shared/components/sidebar/SideItem.tsx (1)

37-37: 시각적 힌트 추가는 적절합니다

cursor-pointertransition-colors 추가로 상호작용 affordance가 좋아졌습니다.

apps/client/src/shared/components/optionsMenuButton/OptionsMenuButton.tsx (1)

12-12: 좌측 정렬 패딩 변경 OK

justify-center 제거 후 pl-[0.8rem]으로 좌측 정렬 의도 반영된 것 확인했습니다.

packages/design-system/src/components/card/RemindCard.tsx (1)

25-25: BaseCard height를 외부에서 주입하도록 변경한 점 좋습니다

className="h-[35.6rem]"으로 카드 높이를 명시적으로 제어하게 되어 베이스 컴포넌트의 응집도가 좋아졌습니다.

packages/design-system/src/components/card/MyBookmarkCard.tsx (1)

25-25: BaseCard height 주입 패턴 일관성 확보 👍

RemindCard와 동일한 패턴으로 높이를 주입하여 디자인 일관성과 재사용성을 높였습니다.

packages/design-system/src/components/card/BaseCard.tsx (2)

6-6: className 위임 및 cn 머지 사용 변경은 적절합니다

레이아웃 확장성(높이/여백 제어)이 확보되었습니다. 디자인시스템 컴포넌트로서 방향성 👍

Also applies to: 13-16


1-1: 확인 완료 — '../../lib'가 cn을 재export합니다
packages/design-system/src/lib/index.ts가 './utils'를 export * 하고 있으며 packages/design-system/src/lib/utils.ts에 cn이 정의되어 있으므로 import 경로 변경 불필요.

apps/client/src/pages/myBookmark/MyBookmark.tsx (1)

79-81: REMIND_MOCK_DATA 사용 의도 확인

북마크 페이지에서 리마인드 상수로 카테고리명을 조회하는 것이 의도인지 확인이 필요합니다(네이밍/도메인 혼동 가능).

원하시면 카테고리 소스 일원화/타입 보강을 위한 리팩터를 제안하겠습니다.

apps/client/src/pages/remind/Remind.tsx (2)

65-71: 빈 상태 분기 LGTM

전체 무자료/읽음/안읽음 상태 분리 로직이 명확합니다.


29-35: React Query v5 사용 여부 확인 및 로딩 UI 통일

package.json에서 @tanstack/react-query를 찾을 수 없습니다 (실행한 jq 스크립트 결과: null). isPending는 v5 전제입니다 — 코드베이스에서 '@tanstack/react-query' 또는 'react-query' 임포트/lockfile을 검색해 실제 설치 버전을 확인하고, v5가 아니라면 isPending 사용을 교체(예: isLoading/isFetching)하세요. 로딩 UI는 디자인시스템의 Progress 컴포넌트로 통일 권장. (위치: apps/client/src/pages/remind/Remind.tsx: 29-35, 73-76)

Comment on lines +9 to +16
const BaseCard = ({ children, onClick, className }: BaseCardProps) => {
return (
<div
onClick={onClick}
className="border-gray200 w-[24.8rem] overflow-hidden rounded-[1.2rem] border bg-white h-[12rem]"
className={cn(
'border-gray200 w-[24.8rem] overflow-hidden rounded-[1.2rem] border bg-white',
className
)}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

클릭 가능한 div의 키보드 접근성 보완 필요

onClick만 부여된 div는 키보드로 포커스/활성화가 어려워 a11y 이슈입니다. onClick 존재 시 role/tabIndex/Enter·Space 핸들링을 추가하세요.

다음 패치를 제안합니다:

-const BaseCard = ({ children, onClick, className }: BaseCardProps) => {
+const BaseCard = ({ children, onClick, className }: BaseCardProps) => {
+  const isInteractive = Boolean(onClick);
   return (
     <div
-      onClick={onClick}
+      onClick={onClick}
+      role={isInteractive ? 'button' : undefined}
+      tabIndex={isInteractive ? 0 : undefined}
+      onKeyDown={
+        isInteractive
+          ? (e) => {
+              if (e.key === 'Enter' || e.key === ' ') {
+                e.preventDefault();
+                onClick?.();
+              }
+            }
+          : undefined
+      }
       className={cn(
         'border-gray200 w-[24.8rem] overflow-hidden rounded-[1.2rem] border bg-white',
         className
       )}
     >
       {children}
     </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.

Suggested change
const BaseCard = ({ children, onClick, className }: BaseCardProps) => {
return (
<div
onClick={onClick}
className="border-gray200 w-[24.8rem] overflow-hidden rounded-[1.2rem] border bg-white h-[12rem]"
className={cn(
'border-gray200 w-[24.8rem] overflow-hidden rounded-[1.2rem] border bg-white',
className
)}
const BaseCard = ({ children, onClick, className }: BaseCardProps) => {
const isInteractive = Boolean(onClick);
return (
<div
onClick={onClick}
role={isInteractive ? 'button' : undefined}
tabIndex={isInteractive ? 0 : undefined}
onKeyDown={
isInteractive
? (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
onClick?.();
}
}
: undefined
}
className={cn(
'border-gray200 w-[24.8rem] overflow-hidden rounded-[1.2rem] border bg-white',
className
)}
>
{children}
</div>
);
}
🤖 Prompt for AI Agents
In packages/design-system/src/components/card/BaseCard.tsx around lines 9 to 16,
the component renders a div with an onClick but no keyboard accessibility; when
onClick is provided add role="button", tabIndex={0}, and an onKeyDown handler
that calls the same onClick for Enter (key === 'Enter') and Space (key === ' '
or key === 'Spacebar') while preventing default for Space to avoid page scroll;
ensure these additions are only applied when onClick is present and preserve
existing className/children behavior.

@constantly-dev constantly-dev changed the title sp1 1차 QA 반영 (대시보드) sp1 1차 QA 반영 (대시보드-UI관련) Sep 17, 2025
@constantly-dev constantly-dev merged commit b923743 into develop Sep 17, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix 버그 수정하라 러브버그

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Fix] sp1 QA 대시보드 1차 반영

1 participant