mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-07 02:58:15 +00:00
fix: use JavaScript-based hover for checkpoint menu visibility (#10056)
This commit is contained in:
parent
4771de1ebc
commit
a3b258ad62
2 changed files with 62 additions and 11 deletions
|
|
@ -18,6 +18,7 @@ export const CheckpointSaved = ({ checkpoint, currentHash, ...props }: Checkpoin
|
|||
const isCurrent = currentHash === props.commitHash
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
|
||||
const [isClosing, setIsClosing] = useState(false)
|
||||
const [isHovering, setIsHovering] = useState(false)
|
||||
const closeTimer = useRef<number | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -46,7 +47,16 @@ export const CheckpointSaved = ({ checkpoint, currentHash, ...props }: Checkpoin
|
|||
}
|
||||
}
|
||||
|
||||
const menuVisible = isPopoverOpen || isClosing
|
||||
const handleMouseEnter = () => {
|
||||
setIsHovering(true)
|
||||
}
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
setIsHovering(false)
|
||||
}
|
||||
|
||||
// Menu is visible when hovering, popover is open, or briefly after popover closes
|
||||
const menuVisible = isHovering || isPopoverOpen || isClosing
|
||||
|
||||
const metadata = useMemo(() => {
|
||||
if (!checkpoint) {
|
||||
|
|
@ -67,7 +77,10 @@ export const CheckpointSaved = ({ checkpoint, currentHash, ...props }: Checkpoin
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="group flex items-center justify-between gap-2 pt-2 pb-3 ">
|
||||
<div
|
||||
className="flex items-center justify-between gap-2 pt-2 pb-3"
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}>
|
||||
<div className="flex items-center gap-2 text-blue-400 whitespace-nowrap">
|
||||
<GitCommitVertical className="w-4" />
|
||||
<span className="font-semibold">{t("chat:checkpoint.regular")}</span>
|
||||
|
|
@ -80,10 +93,8 @@ export const CheckpointSaved = ({ checkpoint, currentHash, ...props }: Checkpoin
|
|||
"linear-gradient(90deg, rgba(0, 188, 255, .65), rgba(0, 188, 255, .65) 80%, rgba(0, 188, 255, 0) 99%)",
|
||||
}}></span>
|
||||
|
||||
{/* Keep menu visible while popover is open or briefly after close to prevent jump */}
|
||||
<div
|
||||
data-testid="checkpoint-menu-container"
|
||||
className={cn("h-4 -mt-2", menuVisible ? "block" : "hidden group-hover:block")}>
|
||||
{/* Keep menu visible while hovering, popover is open, or briefly after close to prevent jump */}
|
||||
<div data-testid="checkpoint-menu-container" className={cn("h-4 -mt-2", menuVisible ? "block" : "hidden")}>
|
||||
<CheckpointMenu
|
||||
ts={props.ts}
|
||||
commitHash={props.commitHash}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ vi.mock("@/components/ui", () => {
|
|||
}
|
||||
})
|
||||
|
||||
import { render, waitFor, screen } from "@/utils/test-utils"
|
||||
import { render, waitFor, screen, fireEvent } from "@/utils/test-utils"
|
||||
import React from "react"
|
||||
import userEvent from "@testing-library/user-event"
|
||||
import { CheckpointSaved } from "../CheckpointSaved"
|
||||
|
|
@ -54,7 +54,7 @@ describe("CheckpointSaved popover visibility", () => {
|
|||
|
||||
const getMenu = () => getByTestId("checkpoint-menu-container") as HTMLElement
|
||||
|
||||
// Initially hidden (relies on group-hover)
|
||||
// Initially hidden (not hovering)
|
||||
expect(getMenu()).toBeTruthy()
|
||||
expect(getMenu().className).toContain("hidden")
|
||||
|
||||
|
|
@ -80,7 +80,12 @@ describe("CheckpointSaved popover visibility", () => {
|
|||
})
|
||||
|
||||
it("resets confirm state when popover closes", async () => {
|
||||
const { getByTestId } = render(<CheckpointSaved {...baseProps} />)
|
||||
const { getByTestId, container } = render(<CheckpointSaved {...baseProps} />)
|
||||
const getParentDiv = () =>
|
||||
container.querySelector("[class*='flex items-center justify-between']") as HTMLElement
|
||||
|
||||
// Hover to make menu visible
|
||||
fireEvent.mouseEnter(getParentDiv())
|
||||
|
||||
// Open the popover
|
||||
await waitForOpenHandler()
|
||||
|
|
@ -106,10 +111,12 @@ describe("CheckpointSaved popover visibility", () => {
|
|||
})
|
||||
|
||||
it("closes popover after preview and after confirm restore", async () => {
|
||||
const { getByTestId } = render(<CheckpointSaved {...baseProps} />)
|
||||
const { getByTestId, container } = render(<CheckpointSaved {...baseProps} />)
|
||||
|
||||
const popoverRoot = () => getByTestId("restore-popover")
|
||||
const menuContainer = () => getByTestId("checkpoint-menu-container")
|
||||
const getParentDiv = () =>
|
||||
container.querySelector("[class*='flex items-center justify-between']") as HTMLElement
|
||||
|
||||
// Open
|
||||
await waitForOpenHandler()
|
||||
|
|
@ -125,11 +132,16 @@ describe("CheckpointSaved popover visibility", () => {
|
|||
expect(popoverRoot().getAttribute("data-open")).toBe("false")
|
||||
expect(menuContainer().className).toContain("block")
|
||||
})
|
||||
|
||||
// Simulate mouse leaving the component to trigger hide
|
||||
fireEvent.mouseLeave(getParentDiv())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(menuContainer().className).toContain("hidden")
|
||||
})
|
||||
|
||||
// Reopen
|
||||
// Hover to make menu visible again, then reopen
|
||||
fireEvent.mouseEnter(getParentDiv())
|
||||
lastOnOpenChange?.(true)
|
||||
await waitFor(() => {
|
||||
expect(popoverRoot().getAttribute("data-open")).toBe("true")
|
||||
|
|
@ -141,8 +153,36 @@ describe("CheckpointSaved popover visibility", () => {
|
|||
await waitFor(() => {
|
||||
expect(popoverRoot().getAttribute("data-open")).toBe("false")
|
||||
})
|
||||
|
||||
// Simulate mouse leaving the component to trigger hide
|
||||
fireEvent.mouseLeave(getParentDiv())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(menuContainer().className).toContain("hidden")
|
||||
})
|
||||
})
|
||||
|
||||
it("shows menu on hover and hides when mouse leaves", async () => {
|
||||
const { getByTestId, container } = render(<CheckpointSaved {...baseProps} />)
|
||||
|
||||
const getMenu = () => getByTestId("checkpoint-menu-container") as HTMLElement
|
||||
const getParentDiv = () =>
|
||||
container.querySelector("[class*='flex items-center justify-between']") as HTMLElement
|
||||
|
||||
// Initially hidden (not hovering)
|
||||
expect(getMenu().className).toContain("hidden")
|
||||
|
||||
// Hover over the component
|
||||
fireEvent.mouseEnter(getParentDiv())
|
||||
await waitFor(() => {
|
||||
expect(getMenu().className).toContain("block")
|
||||
expect(getMenu().className).not.toContain("hidden")
|
||||
})
|
||||
|
||||
// Mouse leaves the component
|
||||
fireEvent.mouseLeave(getParentDiv())
|
||||
await waitFor(() => {
|
||||
expect(getMenu().className).toContain("hidden")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue