Skip to content

fix(#676): prevent stuck sidebar branch tooltip (A+B+C)#678

Merged
Kewton merged 2 commits intodevelopfrom
feature/676-worktree
Apr 24, 2026
Merged

fix(#676): prevent stuck sidebar branch tooltip (A+B+C)#678
Kewton merged 2 commits intodevelopfrom
feature/676-worktree

Conversation

@Kewton
Copy link
Copy Markdown
Owner

@Kewton Kewton commented Apr 24, 2026

Summary

サイドバーのブランチ tooltip が isTooltipVisible=true のまま固着し、mouseleave/blur 後も画面に残り続ける不具合を、多層防御 (A+B+C) で修正します。Issue #675 の無限ループ中に React の mouseleave 合成イベントがレース状態に陥り state が落ちないケースに対する防御的修正です。

Closes #676

Root cause

BranchListItem.tsx の tooltip は portal で DOM に常時存在し、opacity のみで表示制御していたため、setIsTooltipVisible(false) が dispatch されない瞬間に state が true で固定されるとユーザーから永久に残って見える構造でした。state を信頼しすぎない実装へ変更します。

Changes

Fixed (A+B+C)

  • A: 選択中ブランチでは tooltip を表示しない
    • showTooltip = isTooltipVisible && !isSelected でゲート
    • スクショ症状(選択済みブランチで tooltip 残留)を解消
  • B: click 時に明示的に state を false にする
    • handleClick ラッパーで setIsTooltipVisible(false) 後に props.onClick を呼ぶ
    • onMouseLeave スキップに依存しない確実なトリガを追加
  • C: isVisible=false 時に portal の中身を null にして DOM から物理除去
    • Hook 順序維持のため useStateuseEffect → early return の順
    • stale な opacity: isVisible ? 1 : 0 スタイルと「Always present in DOM」JSDoc を削除
    • aria-describedby は tooltip が実際に DOM に存在する時のみ button に付与(アクセシビリティ改善)

Tests

  • 新規 9 テスト追加(初期非表示、mouseEnter/mouseLeave、focus/blur、click 消去、onClick 発火、選択中抑止、aria-describedby ゲート)
  • 既存 10 テスト更新(mouseEnter を事前発火して tooltip 表示状態を明示)
  • Sidebar.test.tsx>=3>=1 に緩和(常時マウント前提だった暗黙の期待を修正)

Files changed

  • src/components/sidebar/BranchListItem.tsx
  • tests/unit/components/sidebar/BranchListItem.test.tsx
  • tests/unit/components/layout/Sidebar.test.tsx
  • dev-reports/bug-fix/issue676_20260424_201938/ (investigation/work-plan/TDD/acceptance artifacts)

Test Results

  • ESLint: 0 errors / 0 warnings
  • TypeScript (tsc --noEmit): 0 errors
  • Unit tests: 6390 passed / 7 skipped / 0 failed (340 files)
    • BranchListItem.test.tsx: 45/45 passed
  • Build (npm run build): success

Acceptance criteria

  • 選択中ブランチでは tooltip が表示されない
  • mouseLeave で tooltip が消える
  • click で tooltip が即座に消える
  • focus→blur で tooltip が消える
  • isVisible=false のとき tooltip div が DOM に存在しない
  • aria-describedby は tooltip 実在時のみ付与
  • 既存の tooltip 表示機能・CLI status dots・unread indicator に影響なし
  • lint/tsc/unit test/build 全 pass

Related

Checklist

  • Unit tests pass
  • Lint check passes
  • Type check passes
  • Build succeeds
  • No console.log in production code

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

Kewton and others added 2 commits April 24, 2026 20:26
Tooltip was persistently visible after React concurrent re-renders lost
the synthetic mouseleave, leaving `isTooltipVisible=true` stuck on the
previously-hovered branch.

- A: skip rendering the tooltip for the currently selected branch so a
  stale visibility flag does not linger on the focused item.
- B: wrap the button onClick to explicitly reset `isTooltipVisible` to
  false before forwarding to the parent handler.
- C: unmount the portal contents when not visible instead of keeping an
  empty tooltip node in the DOM; only attach aria-describedby while the
  tooltip is actually rendered so screen readers do not chase a dangling
  reference.

Tests updated: existing tooltip-content assertions now fire mouseEnter
first, and new tests cover initial-render absence, selected-branch
absence, click-dismisses-tooltip, focus/blur lifecycle, and
aria-describedby gating.
…eptance)

Investigation, work-plan, TDD and acceptance artifacts for the sidebar
tooltip stuck bug fix (A+B+C defensive guard).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Kewton Kewton added the bug Something isn't working label Apr 24, 2026
@Kewton Kewton merged commit ce337c2 into develop Apr 24, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant