refactor: simplify hover menu logic and update related tests for workspace switcher
This commit is contained in:
@@ -14,8 +14,11 @@ it("wraps the dropdown label in a Base UI menu group", async () => {
|
|||||||
assert.match(source, /<DropdownMenuGroup>[\s\S]*<DropdownMenuLabel>\{t\("workspace\.switchWorkspace"\)\}<\/DropdownMenuLabel>/);
|
assert.match(source, /<DropdownMenuGroup>[\s\S]*<DropdownMenuLabel>\{t\("workspace\.switchWorkspace"\)\}<\/DropdownMenuLabel>/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not auto-open the rail menu from focus events", async () => {
|
it("does not auto-open the rail menu from focus or hover events", async () => {
|
||||||
assert.doesNotMatch(source, /onFocus=\{openHoverMenu\}/);
|
assert.doesNotMatch(source, /onFocus=\{openHoverMenu\}/);
|
||||||
assert.doesNotMatch(source, /onBlur=\{closeHoverMenu\}/);
|
assert.doesNotMatch(source, /onBlur=\{closeHoverMenu\}/);
|
||||||
|
assert.doesNotMatch(source, /onPointerEnter=\{openHoverMenu\}/);
|
||||||
|
assert.doesNotMatch(source, /onPointerLeave=\{closeHoverMenu\}/);
|
||||||
|
assert.doesNotMatch(source, /hoverOpen/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { CheckIcon, ChevronsUpDownIcon } from "lucide-react"
|
import { CheckIcon, ChevronsUpDownIcon } from "lucide-react"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { useEffect, useRef, useState } from "react"
|
|
||||||
import type { ReactElement } from "react"
|
import type { ReactElement } from "react"
|
||||||
|
|
||||||
import { useI18n } from "@/i18n/provider"
|
import { useI18n } from "@/i18n/provider"
|
||||||
@@ -52,44 +51,9 @@ export function WorkspaceSwitcher({
|
|||||||
trigger,
|
trigger,
|
||||||
}: WorkspaceSwitcherProps) {
|
}: WorkspaceSwitcherProps) {
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const [hoverOpen, setHoverOpen] = useState(false)
|
|
||||||
const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
||||||
const isRail = variant === "rail"
|
|
||||||
const currentOption =
|
const currentOption =
|
||||||
workspaceOptions.find((item) => item.key === currentWorkspace) ?? workspaceOptions[0]
|
workspaceOptions.find((item) => item.key === currentWorkspace) ?? workspaceOptions[0]
|
||||||
|
|
||||||
const clearCloseTimer = () => {
|
|
||||||
if (closeTimerRef.current) {
|
|
||||||
clearTimeout(closeTimerRef.current)
|
|
||||||
closeTimerRef.current = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const openHoverMenu = () => {
|
|
||||||
if (!isRail) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
clearCloseTimer()
|
|
||||||
setHoverOpen(true)
|
|
||||||
}
|
|
||||||
const closeHoverMenu = () => {
|
|
||||||
if (!isRail) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
clearCloseTimer()
|
|
||||||
closeTimerRef.current = setTimeout(() => {
|
|
||||||
setHoverOpen(false)
|
|
||||||
closeTimerRef.current = null
|
|
||||||
}, 120)
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
if (closeTimerRef.current) {
|
|
||||||
clearTimeout(closeTimerRef.current)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const triggerClassName = cn(
|
const triggerClassName = cn(
|
||||||
"gap-2 text-left",
|
"gap-2 text-left",
|
||||||
variant === "header" &&
|
variant === "header" &&
|
||||||
@@ -134,13 +98,8 @@ export function WorkspaceSwitcher({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu
|
<DropdownMenu>
|
||||||
open={isRail ? hoverOpen : undefined}
|
|
||||||
onOpenChange={isRail ? setHoverOpen : undefined}
|
|
||||||
>
|
|
||||||
<DropdownMenuTrigger
|
<DropdownMenuTrigger
|
||||||
onPointerEnter={openHoverMenu}
|
|
||||||
onPointerLeave={closeHoverMenu}
|
|
||||||
render={
|
render={
|
||||||
trigger ?? <Button variant="ghost" className={triggerClassName} />
|
trigger ?? <Button variant="ghost" className={triggerClassName} />
|
||||||
}
|
}
|
||||||
@@ -151,8 +110,6 @@ export function WorkspaceSwitcher({
|
|||||||
align="start"
|
align="start"
|
||||||
side={variant === "sidebar" || variant === "rail" ? "right" : "bottom"}
|
side={variant === "sidebar" || variant === "rail" ? "right" : "bottom"}
|
||||||
sideOffset={8}
|
sideOffset={8}
|
||||||
onPointerEnter={openHoverMenu}
|
|
||||||
onPointerLeave={closeHoverMenu}
|
|
||||||
className="w-60 min-w-60"
|
className="w-60 min-w-60"
|
||||||
>
|
>
|
||||||
<DropdownMenuGroup>
|
<DropdownMenuGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user