You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
spa_instat_tv/src/hooks/useTooltip.tsx

89 lines
2.4 KiB

import type { CSSProperties, MouseEvent } from 'react'
import { useState } from 'react'
import isUndefined from 'lodash/isUndefined'
import { useToggle } from './useToggle'
type TooltipParams = {
anchorId?: string,
horizontalPosition?: 'left' | 'center' | 'right',
indent?: number,
tooltipText: string,
verticalPosition?: 'top' | 'bottom',
}
export const useTooltip = () => {
const [stateTooltipStyle, setTooltipStyle] = useState<CSSProperties>({})
const [stateAnchorId, setAnchorId] = useState<string | null>(null)
const [stateTooltipText, setTooltipText] = useState('')
const {
close: hideTooltip,
isOpen: isTooltipShown,
open: showTooltip,
} = useToggle()
const onMouseOver = ({
anchorId,
horizontalPosition = 'center',
indent = 10,
tooltipText,
verticalPosition = 'bottom',
}: TooltipParams) => (e: MouseEvent<HTMLElement>) => {
const target = e.target as HTMLElement
if (anchorId && target.id !== anchorId) return
const {
left,
right,
top,
} = target.getBoundingClientRect()
const coords: Partial<DOMRect> = {
top: verticalPosition === 'bottom'
? top + target.clientHeight + indent
: top - target.clientHeight - indent,
...(horizontalPosition === 'center' && { left: left + target.clientWidth / 2 }),
...(horizontalPosition === 'left' && { left }),
...(horizontalPosition === 'right' && { right }),
}
const tooltipStyle: CSSProperties = {
left: !isUndefined(coords.left) ? `${coords.left}px` : 'auto',
position: 'fixed',
right: !isUndefined(coords.right) ? `${window.innerWidth - coords.right}px` : 'auto',
top: `${coords.top}px`,
zIndex: 999,
...(horizontalPosition === 'center' && { transform: 'translateX: (-50%)' }),
...(verticalPosition === 'top' && { transform: 'translateY: (-50%)' }),
...(horizontalPosition === 'center' && verticalPosition === 'top' && { transform: 'translate: (-50%, -50%)' }),
}
if (anchorId) {
setAnchorId(anchorId)
}
setTooltipStyle(tooltipStyle)
showTooltip()
setTooltipText(tooltipText)
}
const onMouseLeave = () => {
hideTooltip()
setAnchorId(null)
setTooltipStyle({})
}
return {
anchorId: stateAnchorId,
isTooltipShown,
onMouseLeave,
onMouseOver,
tooltipStyle: stateTooltipStyle,
tooltipText: stateTooltipText,
}
}