feat: implement TooltipManager for managing tooltip lifecycle (#24236)
Co-authored-by: crazywoola <427733928@qq.com>
This commit is contained in:
parent
c5614d04d2
commit
6b01b0b165
2 changed files with 25 additions and 2 deletions
16
web/app/components/base/tooltip/TooltipManager.ts
Normal file
16
web/app/components/base/tooltip/TooltipManager.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
class TooltipManager {
|
||||||
|
private activeCloser: (() => void) | null = null
|
||||||
|
|
||||||
|
register(closeFn: () => void) {
|
||||||
|
if (this.activeCloser)
|
||||||
|
this.activeCloser()
|
||||||
|
this.activeCloser = closeFn
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(closeFn: () => void) {
|
||||||
|
if (this.activeCloser === closeFn)
|
||||||
|
this.activeCloser = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const tooltipManager = new TooltipManager()
|
||||||
|
|
@ -6,6 +6,8 @@ import type { OffsetOptions, Placement } from '@floating-ui/react'
|
||||||
import { RiQuestionLine } from '@remixicon/react'
|
import { RiQuestionLine } from '@remixicon/react'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
|
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
|
||||||
|
import { tooltipManager } from './TooltipManager'
|
||||||
|
|
||||||
export type TooltipProps = {
|
export type TooltipProps = {
|
||||||
position?: Placement
|
position?: Placement
|
||||||
triggerMethod?: 'hover' | 'click'
|
triggerMethod?: 'hover' | 'click'
|
||||||
|
|
@ -56,22 +58,26 @@ const Tooltip: FC<TooltipProps> = ({
|
||||||
isHoverTriggerRef.current = isHoverTrigger
|
isHoverTriggerRef.current = isHoverTrigger
|
||||||
}, [isHoverTrigger])
|
}, [isHoverTrigger])
|
||||||
|
|
||||||
|
const close = () => setOpen(false)
|
||||||
|
|
||||||
const handleLeave = (isTrigger: boolean) => {
|
const handleLeave = (isTrigger: boolean) => {
|
||||||
if (isTrigger)
|
if (isTrigger)
|
||||||
setNotHoverTrigger()
|
setNotHoverTrigger()
|
||||||
|
|
||||||
else
|
else
|
||||||
setNotHoverPopup()
|
setNotHoverPopup()
|
||||||
|
|
||||||
// give time to move to the popup
|
// give time to move to the popup
|
||||||
if (needsDelay) {
|
if (needsDelay) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!isHoverPopupRef.current && !isHoverTriggerRef.current)
|
if (!isHoverPopupRef.current && !isHoverTriggerRef.current) {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
|
tooltipManager.clear(close)
|
||||||
|
}
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
|
tooltipManager.clear(close)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,6 +93,7 @@ const Tooltip: FC<TooltipProps> = ({
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
if (triggerMethod === 'hover') {
|
if (triggerMethod === 'hover') {
|
||||||
setHoverTrigger()
|
setHoverTrigger()
|
||||||
|
tooltipManager.register(close)
|
||||||
setOpen(true)
|
setOpen(true)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue