Skip to content

[✨ Feat/#57] Tooltip 공통 컴포넌트 구현#58

Merged
Lseojeong merged 4 commits into
devfrom
feat/#57
Jul 1, 2026
Merged

[✨ Feat/#57] Tooltip 공통 컴포넌트 구현#58
Lseojeong merged 4 commits into
devfrom
feat/#57

Conversation

@Lseojeong

@Lseojeong Lseojeong commented Jul 1, 2026

Copy link
Copy Markdown
Member

#️⃣연관된 이슈

체크 사항

  • UI 동작 및 레이아웃 확인
  • 불필요한 console 제거
  • 기능 정상 동작
  • 팀 컨벤션에 맞게 구현했는지
  • 관련 문서 또는 주석을 갱신했는지

📝작업 내용

Tooltip 공통 컴포넌트 구현

  • Tooltip.Root, Tooltip.Trigger, Tooltip.Content, Tooltip.Arrow compound 구조를 추가했습니다.
  • hover와 focus 상태로 Tooltip을 열고 닫을 수 있도록 구현했습니다.
  • top, right, bottom, left 위치를 지원합니다.
  • Content는 기본적으로 portal을 통해 document.body에 렌더링되도록 구성했습니다.
  • Tooltip 표시/숨김 전환 애니메이션과 reduced motion 대응을 추가했습니다.

스타일 토큰 정리

  • Tooltip z-index를 --z-index-tooltip 토큰으로 분리했습니다.
  • Tooltip shadow를 --shadow-tooltip 토큰으로 정리했습니다.

스크린샷 (선택)

image

추가한 라이브러리 (선택)

  • 없음

💬리뷰 요구사항(선택)

Summary by CodeRabbit

  • New Features
    • 툴팁 컴파운드 컴포넌트(Tooltip, Trigger, Content, Arrow) 추가로 트리거/콘텐츠/화살표를 한 번에 구성할 수 있게 되었습니다.
    • 배치(상/하/좌/우), 오픈/클로즈, 포털 렌더링 옵션 및 그림자 스타일 적용이 지원됩니다.
    • 스토리북 예제(배치별/텍스트 트리거)로 사용 시나리오를 확인할 수 있습니다.
  • Bug Fixes
    • 툴팁용 z-index 및 그림자 토큰이 추가되어 레이어 겹침과 시각적 일관성이 개선되었습니다.

@Lseojeong Lseojeong self-assigned this Jul 1, 2026
@Lseojeong Lseojeong added the ✨Feature 새로운 기능 구현 label Jul 1, 2026
@Lseojeong Lseojeong linked an issue Jul 1, 2026 that may be closed by this pull request
11 tasks
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
rewrite Ready Ready Preview, Comment Jul 1, 2026 1:45pm

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ccd725f4-6bea-48df-bd38-c16d5f9ef641

📥 Commits

Reviewing files that changed from the base of the PR and between 3111ab7 and f0dc38c.

📒 Files selected for processing (6)
  • src/shared/styles/base/colors.css
  • src/shared/ui/tooltip/Tooltip.stories.tsx
  • src/shared/ui/tooltip/Tooltip.tsx
  • src/shared/ui/tooltip/Tooltip.types.ts
  • src/shared/ui/tooltip/TooltipArrow.tsx
  • src/shared/ui/tooltip/TooltipTrigger.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/shared/ui/tooltip/Tooltip.types.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/shared/styles/base/colors.css
  • src/shared/ui/tooltip/TooltipArrow.tsx
  • src/shared/ui/tooltip/Tooltip.stories.tsx
  • src/shared/ui/tooltip/Tooltip.tsx
  • src/shared/ui/tooltip/TooltipTrigger.tsx

Walkthrough

Tooltip compound 컴포넌트와 관련 타입, 컨텍스트, 스타일 토큰, Storybook 예시가 추가되었습니다. Root는 상태와 위치를 관리하고, Trigger/Content/Arrow가 연결되며, public export가 정리되었습니다.

Changes

Tooltip 컴포넌트 구현

Layer / File(s) Summary
공개 타입 정의
src/shared/ui/tooltip/Tooltip.types.ts
TooltipProps, TooltipTriggerProps, TooltipContentProps, TooltipArrowProps, 상태/액션/컨텍스트 타입을 정의하고 export합니다.
Context 정의
src/shared/ui/tooltip/TooltipContext.ts
TooltipContext와 컨텍스트 부재 시 예외를 던지는 useTooltipContext 훅을 정의합니다.
Root 상태 관리 및 위치 계산
src/shared/ui/tooltip/Tooltip.tsx
getTooltipPosition 유틸, controlled/uncontrolled open 상태 관리, 포커스/포인터 추적, 닫힘 지연, scroll/resize 기반 위치 재계산을 구현합니다.
Trigger 구현
src/shared/ui/tooltip/TooltipTrigger.tsx
asChild 분기에 따른 슬롯 확장/버튼 렌더링과 이벤트 핸들러 조합을 구현합니다.
Content/Arrow 구현
src/shared/ui/tooltip/TooltipContent.tsx, src/shared/ui/tooltip/TooltipArrow.tsx
cva 기반 placement/open 상태 스타일, portal 렌더링, 화살표 방향 스타일을 구현합니다.
공개 export 및 스타일 토큰
src/shared/ui/tooltip/Tooltip.tsx, src/shared/ui/tooltip/index.ts, src/shared/styles/base/colors.css, src/shared/styles/base/z-index.css
Tooltip 정적 멤버 구성 및 export, tooltip용 shadow/z-index CSS 토큰을 추가합니다.
Storybook 문서화
src/shared/ui/tooltip/Tooltip.stories.tsx
meta 설정과 Playground/Placements/TextTrigger 스토리를 추가합니다.

Estimated code review effort: 3 (Moderate) | ~30 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 Tooltip 공통 컴포넌트 구현이라는 주요 변경을 정확히 요약합니다.
Linked Issues check ✅ Passed 직접 이슈 #57의 Root/Trigger/Content/Arrow, hover/focus, 위치, 애니메이션, Portal, Storybook 요구를 충족합니다.
Out of Scope Changes check ✅ Passed 툴팁 구현에 필요한 타입, 스타일 토큰, 스토리 추가 외에 명백한 무관 변경은 보이지 않습니다.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#57

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

🧪 테스트 결과

항목 결과
✅ Jest 테스트 success

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

🚦 CI 검증 결과

항목 결과
🧠 TypeScript 타입 체크 success
🧹 ESLint 검사 success
🎨 Prettier 검사 success
🏗️ Build 검증 success

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/shared/ui/tooltip/Tooltip.stories.tsx (1)

78-140: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Placements 스토리 중복 구조를 데이터 기반으로 정리 권장.

top/left/right/bottom 4개 블록이 Tooltip.Trigger + Tooltip.Content + Tooltip.Arrow 구조를 거의 동일하게 반복하고 있습니다. placement, 버튼 라벨, 안내 문구만 배열로 뽑아 .map으로 렌더링하면 유지보수가 쉬워집니다.

♻️ 리팩터링 제안
+const placements = [
+  { placement: 'top', label: 'Top', description: '위에 표시됩니다.' },
+  { placement: 'left', label: 'Left', description: '왼쪽에 표시됩니다.' },
+  { placement: 'right', label: 'Right', description: '오른쪽에 표시됩니다.' },
+  { placement: 'bottom', label: 'Bottom', description: '아래에 표시됩니다.' },
+] as const;
+
 export const Placements: Story = {
   render: () => (
     <div className="grid min-h-96 place-items-center bg-black p-16">
       <div className="grid grid-cols-3 items-center gap-6">
         <div />
-        <Tooltip placement="top">
-          <Tooltip.Trigger asChild>
-            <Button className="w-28" variant="secondary">
-              Top
-            </Button>
-          </Tooltip.Trigger>
-          <Tooltip.Content>
-            위에 표시됩니다.
-            <Tooltip.Arrow />
-          </Tooltip.Content>
-        </Tooltip>
+        {placements
+          .filter(({ placement }) => placement === 'top')
+          .map(({ placement, label, description }) => (
+            <Tooltip key={placement} placement={placement}>
+              <Tooltip.Trigger asChild>
+                <Button className="w-28" variant="secondary">
+                  {label}
+                </Button>
+              </Tooltip.Trigger>
+              <Tooltip.Content>
+                {description}
+                <Tooltip.Arrow />
+              </Tooltip.Content>
+            </Tooltip>
+          ))}
         <div />
         {/* ... 나머지 방향도 동일 패턴으로 정리 ... */}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/shared/ui/tooltip/Tooltip.stories.tsx` around lines 78 - 140, The
Placements story in Tooltip.stories.tsx repeats the same Tooltip.Trigger,
Tooltip.Content, and Tooltip.Arrow structure four times for
top/left/right/bottom. Refactor this story into a data-driven render by moving
the placement, button label, and message text into an array and mapping over it
inside the Placements Story render function, keeping the existing Tooltip,
Tooltip.Trigger, Tooltip.Content, Tooltip.Arrow, and Button usage intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/shared/ui/tooltip/Tooltip.tsx`:
- Around line 142-184: The controlled open path in Tooltip can leave content
mounted but still hidden because position initialization only happens through
requestOpenChange and the current layout effect skips updates when open is
driven externally. Update Tooltip’s open-state syncing so external false -> true
changes also reset shouldRenderContent/isPositioned and trigger positioning,
using the existing requestOpenChange, updatePosition, and useLayoutEffect flow.
Make sure the controlled prop change follows the same mount/position setup as
the internal open request path so Tooltip.Content is shown with fresh
coordinates.

In `@src/shared/ui/tooltip/TooltipTrigger.tsx`:
- Around line 107-157: The TooltipTrigger logic is overwriting any existing
aria-describedby value with the tooltip content ID in both the asChild branch
and the button render path. Update TooltipTrigger and its helper usage so the
tooltip ID is merged with any existing aria-describedby on the trigger (for
example via the existing props/child attrs in getSlotProps, cloneSlot, and
getTriggerButtonProps) instead of replacing it, keeping both descriptions
accessible.

---

Nitpick comments:
In `@src/shared/ui/tooltip/Tooltip.stories.tsx`:
- Around line 78-140: The Placements story in Tooltip.stories.tsx repeats the
same Tooltip.Trigger, Tooltip.Content, and Tooltip.Arrow structure four times
for top/left/right/bottom. Refactor this story into a data-driven render by
moving the placement, button label, and message text into an array and mapping
over it inside the Placements Story render function, keeping the existing
Tooltip, Tooltip.Trigger, Tooltip.Content, Tooltip.Arrow, and Button usage
intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 215a2c4b-2aa7-4675-a3cb-ce9c6f9b234b

📥 Commits

Reviewing files that changed from the base of the PR and between 9d79c16 and 3111ab7.

📒 Files selected for processing (10)
  • src/shared/styles/base/colors.css
  • src/shared/styles/base/z-index.css
  • src/shared/ui/tooltip/Tooltip.stories.tsx
  • src/shared/ui/tooltip/Tooltip.tsx
  • src/shared/ui/tooltip/Tooltip.types.ts
  • src/shared/ui/tooltip/TooltipArrow.tsx
  • src/shared/ui/tooltip/TooltipContent.tsx
  • src/shared/ui/tooltip/TooltipContext.ts
  • src/shared/ui/tooltip/TooltipTrigger.tsx
  • src/shared/ui/tooltip/index.ts

Comment thread src/shared/ui/tooltip/Tooltip.tsx
Comment thread src/shared/ui/tooltip/TooltipTrigger.tsx
@Lseojeong Lseojeong merged commit 6efa3b9 into dev Jul 1, 2026
5 checks passed
@Lseojeong Lseojeong deleted the feat/#57 branch July 1, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨Feature 새로운 기능 구현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[✨Feature] Tooltip 공통 컴포넌트 구현

1 participant