Skip to content

fix(wds): 모바일에서 토스트가 닫히지 않는 문제 수정#528

Merged
Sh031224 merged 2 commits intomainfrom
feature/sh031224/toast-snackbar-pointer
Mar 25, 2026
Merged

fix(wds): 모바일에서 토스트가 닫히지 않는 문제 수정#528
Sh031224 merged 2 commits intomainfrom
feature/sh031224/toast-snackbar-pointer

Conversation

@Sh031224
Copy link
Copy Markdown
Collaborator

@Sh031224 Sh031224 commented Mar 25, 2026

Summary

  • 모바일 특정 상황에서 토스트가 자동으로 닫히지 않는 버그 수정
  • pointer: coarse 대신 pointer: fine 미디어 쿼리를 사용하여 커서 디바이스 판별 로직 개선
  • with-interaction 컴포넌트의 @media not (pointer: fine) 정책과 일관성 유지

Changes

  • isNotPointerDevice()isCursorDevice()로 함수명 및 로직 변경
  • 기존: (pointer: coarse) 체크 → 터치 디바이스에서 hover 시 타이머 일시정지가 동작하여 토스트가 안 닫힘
  • 변경: (pointer: fine) 체크 → 마우스/트랙패드에서만 hover 일시정지 동작, pointer: none 디바이스도 올바르게 처리

Test plan

  • 모바일(터치) 디바이스에서 토스트가 duration 후 정상적으로 닫히는지 확인
  • 데스크탑(마우스)에서 토스트 hover 시 타이머 일시정지가 정상 동작하는지 확인
  • 키보드 전용(pointer: none) 환경에서 토스트가 정상적으로 닫히는지 확인

🤖 Generated with Claude Code

Summary by CodeRabbit

릴리스 노트

  • 버그 수정
    • 토스트/스낵바가 마우스(커서) 입력을 감지하는 환경에서만 마우스 오버로 재생/일시정지되도록 개선했습니다. 터치 중심 장치에서는 알림 타이머가 중단되지 않고 정상적으로 종료됩니다.
  • 테스트
    • 다양한 입력 환경(커서 유무)을 시뮬레이션하는 테스트를 추가·보강하여 동작을 검증했습니다.

pointer: coarse 대신 pointer: fine을 사용하여 with-interaction 정책과 일관성 유지하고
pointer: none 디바이스도 올바르게 처리

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 25, 2026

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

토스트의 디바이스 감지 헬퍼가 isNotPointerDevice에서 isCursorDevice로 이름 변경되었고, 미디어 쿼리가 (pointer: coarse)에서 (pointer: fine)로 바뀌었습니다. 훅(useToastAnimation)은 마우스 진입 시 타이머 제어를 이 새 감지 함수로 조건부로 게이트합니다.

Changes

Cohort / File(s) Summary
디바이스 감지 헬퍼
packages/wds/src/components/toast/helpers.ts
익스포트 함수명 변경: isNotPointerDevice()isCursorDevice(); 미디어 쿼리 변경: '(pointer: coarse)''(pointer: fine)', 반환 불리언 반전 효과 발생.
토스트 애니메이션 훅
packages/wds/src/components/toast/hooks.ts
useToastAnimation의 mouse enter 로직에 isCursorDevice() 조건 추가 — 타이머 일시중지/재개 및 남은시간 재계산이 해당 조건 하에서만 실행됨.
테스트 변경
packages/wds/src/components/toast/index.test.tsx, packages/wds/src/components/snackbar/index.test.tsx
window.matchMedia를 명시적으로 목킹하여 커서 가능/불가능 시의 hover/타이머 동작을 각각 검증하는 테스트 추가/수정.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 모바일에서 토스트가 닫히지 않는 문제 수정이라는 변경사항의 핵심 목표를 명확하게 요약하고 있으며, 실제 코드 변경사항(포인터 감지 로직 개선)과 완벽하게 일치합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feature/sh031224/toast-snackbar-pointer

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

@Sh031224 Sh031224 self-assigned this Mar 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 25, 2026

size-limit report 📦

Path Size
wds 2.37 KB (0%)
wds-icon 5 KB (0%)
wds-lottie 83 B (0%)
wds-theme 144 B (0%)
wds-engine 332 B (0%)
wds-nextjs 165 B (0%)

@github-actions
Copy link
Copy Markdown
Contributor

🚀 Preview

Last commit8fa36f0
Preview URLhttps://dev-montage.wanted.co.kr/8fa36f0

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (1)
packages/wds/src/components/toast/hooks.ts (1)

81-103: handleMouseLeave에도 동일한 isCursorDevice() 가드 추가를 고려해 주세요.

handleMouseEnter에는 isCursorDevice() 가드가 추가되었지만, handleMouseLeave에는 없습니다. 터치 디바이스에서 mouseleave 이벤트가 발생할 경우:

  1. handleMouseEnter가 가드에 의해 타이머를 클리어하지 않음
  2. handleMouseLeavestartTimer(remainingTimeRef.current)를 호출
  3. 기존 타이머가 실행 중인 상태에서 새 타이머가 생성될 수 있음

발생 가능성은 낮지만, 일관성과 방어적 코딩을 위해 handleMouseLeave에도 가드를 추가하는 것이 안전합니다.

♻️ 제안하는 수정
 const handleMouseLeave = () => {
-  if (open && remainingTimeRef.current !== undefined) {
+  if (isCursorDevice() && open && remainingTimeRef.current !== undefined) {
     // Restart timer with remaining time
     startTimer(remainingTimeRef.current);
   }
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/wds/src/components/toast/hooks.ts` around lines 81 - 103, The
handleMouseLeave should mirror the cursor-device guard used in handleMouseEnter
to avoid restarting timers on touch devices; update handleMouseLeave to first
check isCursorDevice() (and the existing open && remainingTimeRef.current !==
undefined) before calling startTimer(remainingTimeRef.current), ensuring you
only restart the timer on pointer/cursor devices and prevent creating duplicate
timers; reference symbols: handleMouseLeave, handleMouseEnter, isCursorDevice,
startTimer, remainingTimeRef, open.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/wds/src/components/toast/hooks.ts`:
- Line 83: The global matchMedia mock causes isCursorDevice() to always return
false, breaking hover-pause logic; fix by making the global mock return matches:
true for the '(pointer: fine)' query or override matchMedia within the failing
test to return matches: true for '(pointer: fine)'. Locate usage of
isCursorDevice() in packages/wds/src/components/toast/hooks.ts and update the
test setup in .vitest/setup-tests.ts (or the specific test file) so
window.matchMedia('(pointer: fine)') yields matches: true, ensuring the
mouseEnter handler triggers clearTimer() and the hover pause behavior is
properly validated.

---

Nitpick comments:
In `@packages/wds/src/components/toast/hooks.ts`:
- Around line 81-103: The handleMouseLeave should mirror the cursor-device guard
used in handleMouseEnter to avoid restarting timers on touch devices; update
handleMouseLeave to first check isCursorDevice() (and the existing open &&
remainingTimeRef.current !== undefined) before calling
startTimer(remainingTimeRef.current), ensuring you only restart the timer on
pointer/cursor devices and prevent creating duplicate timers; reference symbols:
handleMouseLeave, handleMouseEnter, isCursorDevice, startTimer,
remainingTimeRef, open.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: db28a3e5-6955-4031-bbf3-eb68e4b8bea7

📥 Commits

Reviewing files that changed from the base of the PR and between 9f54313 and b00bcb9.

📒 Files selected for processing (2)
  • packages/wds/src/components/toast/helpers.ts
  • packages/wds/src/components/toast/hooks.ts

cursor device 여부에 따른 hover 동작을 명시적으로 검증하고
non-cursor device에서 토스트가 정상 닫히는 테스트 케이스 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Sh031224 Sh031224 merged commit 2333887 into main Mar 25, 2026
10 of 11 checks passed
@Sh031224 Sh031224 deleted the feature/sh031224/toast-snackbar-pointer branch March 25, 2026 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant