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
20 changes: 20 additions & 0 deletions apps/client/src/assets/card_img.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions apps/client/src/pages/myBookmark/MyBookmark.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import NoUnreadArticles from '@pages/myBookmark/components/noUnreadArticles/NoUnreadArticles';
import FetchCard from '@pages/myBookmark/components/fetchCard/FetchCard';
import { useInfiniteScroll } from '@shared/hooks/useInfiniteScroll';
import Tooltip from '@shared/components/tooltip/Tooltip';

const MyBookmark = () => {
const [activeBadge, setActiveBadge] = useState<'all' | 'notRead'>('all');
Expand Down Expand Up @@ -175,6 +176,7 @@ const MyBookmark = () => {
isActive={activeBadge === 'notRead'}
/>
</div>
<Tooltip />

{articlesToDisplay.length > 0 ? (
<div
Expand Down
2 changes: 2 additions & 0 deletions apps/client/src/pages/remind/Remind.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useQueryClient } from '@tanstack/react-query';
import NoRemindArticles from './components/noRemindArticles/NoRemindArticles';
import FetchCard from './components/fetchCard/FetchCard';
import { useInfiniteScroll } from '@shared/hooks/useInfiniteScroll';
import Tooltip from '@shared/components/tooltip/Tooltip';

const Remind = () => {
const [isEditOpen, setIsEditOpen] = useState(false);
Expand Down Expand Up @@ -129,6 +130,7 @@ const Remind = () => {
isActive={activeBadge === 'read'}
/>
</div>
<Tooltip />

{articlesToDisplay.length > 0 ? (
<div
Expand Down
20 changes: 20 additions & 0 deletions apps/client/src/shared/components/tooltip/InfoCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import CardImg from '@assets/card_img.svg';
export default function InfoCard() {
return (
<div className="common-shadow bg-white-bg w-[24.6rem] rounded-[12px] px-[1.6rem] py-[2.4rem]">
<p className="sub2-sb text-font-black-1 mb-[1.6rem] text-center">
치삐가 고치고 있어요 <span aria-hidden>🚧</span>
</p>

<div className="mb-[1.6rem] flex justify-center">
<img src={CardImg} alt="메타 정보가 없을 때 표시되는 안내 이미지" />
</div>

<p className="caption2-m text-font-gray-3">
현재 제목과 이미지 자동 불러오기 기능은 개선 중이에요. 저장한 콘텐츠를
쉽게 구분하려면, 메모에 직접 제목이나 키워드를 기록해 두면 더 편리해요.
<span aria-hidden>📝</span>
</p>
</div>
);
}
29 changes: 29 additions & 0 deletions apps/client/src/shared/components/tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Icon } from '@pinback/design-system/icons';
import InfoCard from './InfoCard';

export default function Tooltip() {
return (
<div className="mt-[0.8rem] flex items-center">
<p className="body3-r text-font-gray-3">
일부 콘텐츠는 제목·이미지가 불러와지지 않을 수 있어요.
</p>

<div className="relative inline-flex items-center">
<button
type="button"
aria-describedby="info-card"
className="peer rounded p-[0.4rem]"
>
<Icon name="ic_info" size={16} />
</button>
Comment on lines +12 to +18
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

아이콘 버튼 접근성 레이블 누락

Line [13]의 버튼은 아이콘만 포함하고 있어 스크린 리더에서 이름이 비어 있습니다. aria-label 등을 추가해 의도를 명확히 알려 주세요.

예:

-        <button
-          type="button"
-          aria-describedby="info-card"
-          className="peer rounded p-[0.4rem]"
-        >
+        <button
+          type="button"
+          aria-describedby={infoCardId}
+          aria-label="메타데이터 안내 보기"
+          className="peer rounded p-[0.4rem]"
+        >

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/client/src/shared/components/tooltip/Tooltip.tsx around lines 12 to 18,
the icon-only button lacks an accessible name for screen readers; add an
explicit accessible label such as aria-label or aria-labelledby that describes
the button's purpose (preferably using a localized string from i18n or a prop),
keep aria-describedby if needed, and ensure the label accurately reflects the
tooltip/info action so the button is announced correctly by assistive
technologies.


<div
id="info-card"
className="pointer-events-none absolute left-0 top-[calc(100%+8px)] z-[100] opacity-0 transition-opacity duration-150 peer-hover:opacity-100 peer-focus-visible:opacity-100"
>
<InfoCard />
Comment on lines +20 to +24
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

고정 ID로 인한 중복 위험

Line [21]에서 id="info-card"를 하드코딩하면 Tooltip을 한 페이지에서 여러 번 사용할 때 DOM ID 충돌이 발생합니다. useId 등을 사용해 인스턴스마다 고유 값을 생성하거나 prop으로 받아 처리해 주세요.

예:

-import { Icon } from '@pinback/design-system/icons';
-import InfoCard from './InfoCard';
+import { Icon } from '@pinback/design-system/icons';
+import { useId } from 'react';
+import InfoCard from './InfoCard';
 
 export default function Tooltip() {
+  const infoCardId = useId();
+
   return (
@@
-        <button
-          type="button"
-          aria-describedby="info-card"
+        <button
+          type="button"
+          aria-describedby={infoCardId}
           className="peer rounded p-[0.4rem]"
         >
@@
-        <div
-          id="info-card"
+        <div
+          id={infoCardId}
           className="pointer-events-none absolute left-0 top-[calc(100%+8px)] z-[100] opacity-0 transition-opacity duration-150 peer-hover:opacity-100 peer-focus-visible:opacity-100"
         >
📝 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
<div
id="info-card"
className="pointer-events-none absolute left-0 top-[calc(100%+8px)] z-[100] opacity-0 transition-opacity duration-150 peer-hover:opacity-100 peer-focus-visible:opacity-100"
>
<InfoCard />
// apps/client/src/shared/components/tooltip/Tooltip.tsx
import { Icon } from '@pinback/design-system/icons';
import { useId } from 'react';
import InfoCard from './InfoCard';
export default function Tooltip() {
const infoCardId = useId();
return (
<>
<button
type="button"
aria-describedby={infoCardId}
className="peer rounded p-[0.4rem]"
>
<Icon name="info" />
</button>
<div
id={infoCardId}
className="pointer-events-none absolute left-0 top-[calc(100%+8px)] z-[100] opacity-0 transition-opacity duration-150 peer-hover:opacity-100 peer-focus-visible:opacity-100"
>
<InfoCard />
</div>
</>
);
}
🤖 Prompt for AI Agents
In apps/client/src/shared/components/tooltip/Tooltip.tsx around lines 20 to 24,
the Tooltip uses a hardcoded id="info-card" which can cause DOM ID collisions
when multiple Tooltips are rendered; replace the static id by generating a
unique id per instance (e.g., React's useId or a passed-in prop) and wire that
unique id into the element and any related aria/labeling usage so each Tooltip
instance has a distinct identifier.

</div>
</div>
</div>
);
}
Loading