From ba702474bd364e5fa000ab6726ed5764c3fc2e6e Mon Sep 17 00:00:00 2001 From: SaelixCode Date: Thu, 2 Jul 2026 12:35:37 -0400 Subject: [PATCH] fix: replace cursor-follow tooltip with standard Radix tooltip in sidebar rows Replaced the Cursor/CursorFollow animate-ui primitives in StackRow with the standard Radix Tooltip/TooltipTrigger/TooltipContent already used throughout the app. The custom cursor dot that followed the mouse is gone; tooltips now appear as static popovers on hover/touch. --- frontend/src/components/sidebar/StackRow.tsx | 17 ++++++++--------- .../sidebar/__tests__/StackRow.test.tsx | 18 ++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/sidebar/StackRow.tsx b/frontend/src/components/sidebar/StackRow.tsx index b470539a..0586c6be 100644 --- a/frontend/src/components/sidebar/StackRow.tsx +++ b/frontend/src/components/sidebar/StackRow.tsx @@ -1,10 +1,10 @@ import type { ReactNode } from 'react'; import { GitBranch, Loader2, AlertCircle } from 'lucide-react'; import type { CheckStatus } from '@/types/imageUpdates'; -import { Cursor, CursorContainer, CursorFollow, CursorProvider } from '@/components/animate-ui/primitives/animate/cursor'; import { Checkbox } from '@/components/ui/checkbox'; import type { Label } from '@/components/label-types'; import { cn } from '@/lib/utils'; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { sidebarRowActive, sidebarRowBase, sidebarRowCheckboxSlot } from './sidebar-styles'; import { statusText, statusColor } from './stack-status-utils'; import type { StackRowStatus } from './stack-status-utils'; @@ -34,15 +34,14 @@ interface StackRowProps { function RowTooltip({ trigger, label }: { trigger: ReactNode; label: string }) { return ( - - {trigger} -
- -
+ + + {trigger} + {label} -
-
- + + + ); } diff --git a/frontend/src/components/sidebar/__tests__/StackRow.test.tsx b/frontend/src/components/sidebar/__tests__/StackRow.test.tsx index 7c98c802..a200979c 100644 --- a/frontend/src/components/sidebar/__tests__/StackRow.test.tsx +++ b/frontend/src/components/sidebar/__tests__/StackRow.test.tsx @@ -43,17 +43,15 @@ describe('StackRow', () => { }); it('wraps the partial pill in a hover tooltip', () => { - // jsdom does not mount the cursor-follow label, so assert the PT trigger is - // wrapped in the RowTooltip cursor-container; the visible "3/5 running" - // tooltip text is verified in the Playwright drive. const { container } = render(); - expect(screen.getByText('PT').closest('[data-slot="cursor-container"]')).not.toBeNull(); - expect(container.querySelector('[data-slot="cursor-container"]')).not.toBeNull(); + const trigger = screen.getByText('PT'); + // Radix TooltipTrigger adds data-state to the wrapped element. + expect(trigger.getAttribute('data-state')).toBe('closed'); }); it('does not wrap a non-partial pill in a tooltip', () => { render(); - expect(screen.getByText('UP').closest('[data-slot="cursor-container"]')).toBeNull(); + expect(screen.getByText('UP').getAttribute('data-state')).toBeNull(); }); it('renders cyan rail only when active', () => { @@ -103,12 +101,12 @@ describe('StackRow', () => { }); // ── Image-update check status indicator ──────────────────────────────── - // status='running' renders the pill as plain text (no tooltip), so the only - // cursor-container in these rows is the trailing update/check indicator. it('shows a muted check-failed indicator when the last check failed and there is no update', () => { const { container } = render(); - expect(container.querySelector('[data-slot="cursor-container"]')).not.toBeNull(); + // The trailing slot renders a tooltip-wrapped AlertCircle icon (an SVG). + const trailingSlot = container.querySelector('[data-state="closed"]'); + expect(trailingSlot).not.toBeNull(); // It is not the update dot. expect(container.querySelector('.bg-update')).toBeNull(); }); @@ -120,7 +118,7 @@ describe('StackRow', () => { it('shows no trailing indicator for a clean ok check with no update', () => { const { container } = render(); - expect(container.querySelector('[data-slot="cursor-container"]')).toBeNull(); + expect(container.querySelector('.lucide-alert-circle')).toBeNull(); expect(container.querySelector('.bg-update')).toBeNull(); }); });