Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions apps/client/src/pages/myBookmark/MyBookmark.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
useDeleteRemindArticle,
usePutArticleReadStatus,
} from '@shared/apis/queries';
import NoUnreadArticles from '@pages/myBookmark/components/noUnreadArticles/NoUnreadArticles';

const MyBookmark = () => {
const [activeBadge, setActiveBadge] = useState<'all' | 'notRead'>('all');
Expand Down Expand Up @@ -82,8 +83,15 @@ const MyBookmark = () => {
setActiveBadge(badgeType);
};

const EmptyStateComponent = () => {
if (articles?.totalArticle === 0) {
return <NoArticles />;
}
return <NoUnreadArticles />;
};

return (
<div className="flex h-screen flex-col py-[5.2rem] pl-[8rem]">
<div className="flex h-screen flex-col py-[5.2rem] pl-[8rem] pr-[5rem]">
<div className="flex items-center gap-[0.4rem]">
<div className="flex items-center gap-[0.4rem]">
<p className="head3">나의 북마크</p>
Expand Down Expand Up @@ -116,7 +124,7 @@ const MyBookmark = () => {
</div>

{articlesToDisplay && articlesToDisplay.length > 0 ? (
<div className="scrollbar-hide mt-[2.6rem] flex h-screen max-w-[104rem] flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth">
<div className="scrollbar-hide mt-[2.6rem] flex h-screen flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth">
{articlesToDisplay.map((article) => (
<Card
key={article.articleId}
Expand Down Expand Up @@ -154,7 +162,7 @@ const MyBookmark = () => {
))}
</div>
) : (
<NoArticles />
<EmptyStateComponent />
)}

<OptionsMenuPortal
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import chippiNoRemindArticles from '@assets/chippi_remindx.svg';

const NoUnreadArticles = () => {
return (
<div className="mx-auto mt-[14rem] flex flex-col items-center">
<img src={chippiNoRemindArticles} alt="No Articles" />

<p className="head2 mt-[1.6rem]">저장된 정보를 모두 꺼내봤어요!</p>
<p className="body1-m text-font-gray-3 mt-[0.8rem]">
치삐가 다음 도토리를 기다리고 있어요
</p>
</div>
);
};

export default NoUnreadArticles;
23 changes: 17 additions & 6 deletions apps/client/src/pages/remind/Remind.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
useGetArticleDetail,
} from '@shared/apis/queries';
import { useQueryClient } from '@tanstack/react-query';
import NoRemindArticles from './components/noRemindArticles/NoRemindArticles';

const Remind = () => {
const [isEditOpen, setIsEditOpen] = useState(false);
Expand All @@ -25,7 +26,7 @@ const Remind = () => {

const { mutate: updateToReadStatus } = usePutArticleReadStatus();
const { mutate: deleteArticle } = useDeleteRemindArticle();
const { data } = useGetRemindArticles(
const { data, isPending } = useGetRemindArticles(
formattedDate,
activeBadge === 'read',
1,
Expand Down Expand Up @@ -61,11 +62,21 @@ const Remind = () => {
setActiveBadge(badgeType);
};

const EmptyStateComponent =
activeBadge === 'read' ? <NoReadArticles /> : <NoUnreadArticles />;
const EmptyStateComponent = () => {
if (data?.readArticleCount === 0 && data?.unreadArticleCount === 0) {
return <NoRemindArticles />;
}

return activeBadge === 'read' ? <NoReadArticles /> : <NoUnreadArticles />;
};

// TODO: 로딩 상태 디자인 필요
if (isPending) {
return <div>Loading...</div>;
}

return (
<div className="flex flex-col py-[5.2rem] pl-[8rem]">
<div className="flex flex-col py-[5.2rem] pl-[8rem] pr-[5rem]">
<p className="head3">리마인드</p>
<div className="mt-[3rem] flex gap-[2.4rem]">
<Badge
Expand All @@ -83,7 +94,7 @@ const Remind = () => {
</div>

{data?.articles && data.articles.length > 0 ? (
<div className="scrollbar-hide mt-[2.6rem] flex max-w-[104rem] flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth">
<div className="scrollbar-hide mt-[2.6rem] flex flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth">
{data.articles.map((article) => (
<Card
key={article.articleId}
Expand Down Expand Up @@ -114,7 +125,7 @@ const Remind = () => {
))}
</div>
) : (
EmptyStateComponent
<EmptyStateComponent />
)}

<OptionsMenuPortal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const NoReadArticles = () => {

<p className="head2 mt-[1.6rem]">앗..</p>
<p className="body1-m text-font-gray-3 mt-[0.8rem]">
저장된 정보가 없어요
리마인드에서 안 읽은 북마크를 확인해 보세요.
</p>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import chippiNoArticles from '@assets/chippi_x.svg';

const NoRemindArticles = () => {
return (
<div className="mx-auto mt-[14rem] flex flex-col items-center">
<img src={chippiNoArticles} alt="No Articles" />

<p className="head2 mt-[1.6rem]">앗..</p>
<p className="body1-m text-font-gray-3 mt-[0.8rem]">
저장된 정보가 없어요
</p>
</div>
);
};

export default NoRemindArticles;
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface OptionsMenuButtonProps {

const ITEM_STYLE =
'body4-r text-font-black-1 h-[3.6rem] w-full ' +
'flex items-center justify-center ' +
'flex items-center pl-[0.8rem] ' +
'hover:bg-gray100 focus-visible:bg-gray100 active:bg-gray200 ' +
'outline-none transition-colors';

Expand Down
2 changes: 1 addition & 1 deletion apps/client/src/shared/components/sidebar/SideItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function SideItem({
<div
className={cn(
'flex h-[4.4rem] items-center gap-[0.8rem] rounded-[0.4rem] px-[0.8rem] py-[1.2rem]',
'transition-colors',
'cursor-pointer transition-colors',
active ? 'bg-main0 text-main600' : 'bg-white-bg text-font-gray-2',
className
)}
Expand Down
6 changes: 2 additions & 4 deletions apps/client/src/shared/components/sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ export function Sidebar() {
return (
<aside className="bg-white-bg sticky top-0 h-screen w-[24rem] border-r border-gray-300">
<div className="flex h-full flex-col px-[0.8rem]">
<header className="py-[2.8rem]">
<header className="px-[0.8rem] py-[2.8rem]">
<Icon
name="logo"
aria-label="Pinback 로고"
className="h-[2.4rem] w-[8.7rem]"
className="h-[2.4rem] w-[8.7rem] cursor-pointer"
/>
</header>

Expand All @@ -119,7 +119,6 @@ export function Sidebar() {
label="리마인드"
active={activeTab === 'remind'}
onClick={() => {
setSelectedCategoryId(null);
closeMenu();
goRemind();
}}
Expand All @@ -131,7 +130,6 @@ export function Sidebar() {
active={activeTab === 'mybookmark'}
defaultOpen
onClick={() => {
setSelectedCategoryId(null);
closeMenu();
goBookmarks();
}}
Expand Down
10 changes: 8 additions & 2 deletions packages/design-system/src/components/card/BaseCard.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { cn } from '../../lib';

interface BaseCardProps {
onClick?: () => void;
children: React.ReactNode;
className?: string;
}

const BaseCard = ({ children, onClick }: BaseCardProps) => {
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
)}
Comment on lines +9 to +16
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.

>
{children}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const MyBookmarkCard = ({
onOptionsClick,
}: MyBookmarkCardProps) => {
return (
<BaseCard onClick={onClick}>
<BaseCard onClick={onClick} className="h-[33.8rem]">
<div className="flex h-[12rem] w-full items-center justify-center overflow-hidden bg-[#F8F8FA]">
{imageUrl ? (
<img src={imageUrl} className="h-full w-full object-cover" />
Expand Down
2 changes: 1 addition & 1 deletion packages/design-system/src/components/card/RemindCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const RemindCard = ({
onOptionsClick,
}: RemindCardProps) => {
return (
<BaseCard onClick={onClick}>
<BaseCard onClick={onClick} className="h-[35.6rem]">
<div className="bg-gray900 flex items-center gap-[0.4rem] py-[1.2rem] pl-[1.6rem] text-sm text-white">
<Icon name="ic_clock_active" />
<span className="body2-m text-main400 mr-[0.2rem]">
Expand Down
Loading