webapp/src/lib/createTooltip.ts

73 lines
2.1 KiB
TypeScript
Raw Normal View History

2024-10-03 09:01:44 +00:00
export function createTooltip(referenceElement?: Element, tooltipElement?: HTMLElement, options = {}) {
const defaultOptions = {
placement: 'top',
offset: [0, 8]
}
const config = { ...defaultOptions, ...options }
function updatePosition() {
if (!(referenceElement && tooltipElement)) return
const rect = referenceElement.getBoundingClientRect()
const tooltipRect = tooltipElement.getBoundingClientRect()
const offsetX = config.offset[0]
const offsetY = config.offset[1]
let top = 0
let left = 0
switch (config.placement) {
case 'top': {
top = rect.top - tooltipRect.height - offsetY
left = rect.left + (rect.width - tooltipRect.width) / 2 + offsetX
break
}
case 'bottom': {
top = rect.bottom + offsetY
left = rect.left + (rect.width - tooltipRect.width) / 2 + offsetX
break
}
case 'left': {
top = rect.top + (rect.height - tooltipRect.height) / 2 + offsetY
left = rect.left - tooltipRect.width - offsetX
break
}
case 'right': {
top = rect.top + (rect.height - tooltipRect.height) / 2 + offsetY
left = rect.right + offsetX
break
}
default: {
top = rect.top - tooltipRect.height - offsetY
left = rect.left + (rect.width - tooltipRect.width) / 2 + offsetX
}
}
tooltipElement.style.position = 'absolute'
tooltipElement.style.top = `${top}px`
tooltipElement.style.left = `${left}px`
}
function showTooltip() {
if (tooltipElement) tooltipElement.style.visibility = 'visible'
updatePosition()
}
function hideTooltip() {
if (tooltipElement) tooltipElement.style.visibility = 'hidden'
}
referenceElement?.addEventListener('mouseenter', showTooltip)
referenceElement?.addEventListener('mouseleave', hideTooltip)
window.addEventListener('resize', updatePosition)
return {
update: updatePosition,
destroy() {
referenceElement?.removeEventListener('mouseenter', showTooltip)
referenceElement?.removeEventListener('mouseleave', hideTooltip)
window.removeEventListener('resize', updatePosition)
}
}
}