Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m37s
136 lines
3.8 KiB
React
136 lines
3.8 KiB
React
import { useState, useRef, useEffect } from 'react'
|
|
|
|
/**
|
|
* Tooltip компонент в стиле Tabler UI
|
|
* Использует position: absolute относительно trigger элемента
|
|
*/
|
|
function Tooltip({
|
|
children,
|
|
content,
|
|
position = 'top', // top, bottom, left, right
|
|
shortcut, // keyboard shortcut to display
|
|
delay = 200,
|
|
className = ''
|
|
}) {
|
|
const [isVisible, setIsVisible] = useState(false)
|
|
const timeoutRef = useRef(null)
|
|
const triggerRef = useRef(null)
|
|
|
|
const showTooltip = () => {
|
|
if (timeoutRef.current) clearTimeout(timeoutRef.current)
|
|
|
|
timeoutRef.current = setTimeout(() => {
|
|
setIsVisible(true)
|
|
}, delay)
|
|
}
|
|
|
|
const hideTooltip = () => {
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current)
|
|
}
|
|
setIsVisible(false)
|
|
}
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current)
|
|
}
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<span
|
|
ref={triggerRef}
|
|
onMouseEnter={showTooltip}
|
|
onMouseLeave={hideTooltip}
|
|
onFocus={showTooltip}
|
|
onBlur={hideTooltip}
|
|
className={`tooltip-trigger ${className}`}
|
|
style={{ position: 'relative', display: 'inline-block' }}
|
|
>
|
|
{children}
|
|
|
|
{isVisible && (
|
|
<div
|
|
className={`tooltip bs-tooltip-${position} show`}
|
|
role="tooltip"
|
|
style={{
|
|
position: 'absolute',
|
|
zIndex: 1070,
|
|
display: 'block',
|
|
margin: 0,
|
|
pointerEvents: 'none',
|
|
...(position === 'top' && {
|
|
bottom: '100%',
|
|
left: '50%',
|
|
transform: 'translateX(-50%)',
|
|
marginBottom: '8px'
|
|
}),
|
|
...(position === 'bottom' && {
|
|
top: '100%',
|
|
left: '50%',
|
|
transform: 'translateX(-50%)',
|
|
marginTop: '8px'
|
|
}),
|
|
...(position === 'left' && {
|
|
right: '100%',
|
|
top: '50%',
|
|
transform: 'translateY(-50%)',
|
|
marginRight: '8px'
|
|
}),
|
|
...(position === 'right' && {
|
|
left: '100%',
|
|
top: '50%',
|
|
transform: 'translateY(-50%)',
|
|
marginLeft: '8px'
|
|
})
|
|
}}
|
|
>
|
|
<div className="tooltip-arrow" style={(() => {
|
|
const styles = {
|
|
position: 'absolute',
|
|
width: '8px',
|
|
height: '8px',
|
|
background: 'inherit'
|
|
}
|
|
if (position === 'top') {
|
|
styles.bottom = '0'
|
|
styles.left = '50%'
|
|
styles.transform = 'translateX(-50%) translateY(50%) rotate(45deg)'
|
|
} else if (position === 'bottom') {
|
|
styles.top = '0'
|
|
styles.left = '50%'
|
|
styles.transform = 'translateX(-50%) translateY(-50%) rotate(45deg)'
|
|
} else if (position === 'left') {
|
|
styles.right = '0'
|
|
styles.top = '50%'
|
|
styles.transform = 'translateX(50%) translateY(-50%) rotate(45deg)'
|
|
} else if (position === 'right') {
|
|
styles.left = '0'
|
|
styles.top = '50%'
|
|
styles.transform = 'translateX(-50%) translateY(-50%) rotate(45deg)'
|
|
}
|
|
return styles
|
|
})()}></div>
|
|
<div className="tooltip-inner">
|
|
{content}
|
|
{shortcut && (
|
|
<kbd className="ms-2" style={{
|
|
background: 'rgba(255, 255, 255, 0.2)',
|
|
padding: '0.125rem 0.375rem',
|
|
borderRadius: '0.25rem',
|
|
fontSize: '0.75rem',
|
|
fontFamily: 'monospace'
|
|
}}>{shortcut}</kbd>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</span>
|
|
)
|
|
}
|
|
|
|
export default Tooltip
|
|
|