81 lines
2.7 KiB
TypeScript
81 lines
2.7 KiB
TypeScript
import { watchEffect, watch, onMounted, type CSSProperties, defineComponent, ref } from "vue";
|
|
|
|
const carrierStyle = {
|
|
opacity: "0",
|
|
display: "block",
|
|
pointerEvents: "none",
|
|
backgroundColor: "black",
|
|
border: "white solid 1px",
|
|
color: "white",
|
|
padding: "10px",
|
|
position: "absolute",
|
|
zIndex: "1",
|
|
overflow: "hidden",
|
|
height: "0",
|
|
width: "0",
|
|
transition: "opacity 200ms, height 200ms, width 200ms",
|
|
} satisfies CSSProperties;
|
|
|
|
const textCarrierStyle = {
|
|
fontSize: '16px',
|
|
fontFamily: "Roboto, serif",
|
|
display: "block",
|
|
overflow: "hidden",
|
|
} satisfies CSSProperties;
|
|
|
|
const defaultWidth = 350;
|
|
|
|
export default defineComponent({
|
|
name: "dj-sexy-tooltip",
|
|
props: {
|
|
tooltip: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
},
|
|
setup(props, { slots, attrs }) {
|
|
const active = ref(false);
|
|
|
|
const carrier = ref<HTMLElement | null>(null);
|
|
const textCarrier = ref<HTMLElement | null>(null);
|
|
|
|
onMounted(() => {
|
|
document.addEventListener("mousemove", (event) => {
|
|
const pos = { x: event.pageX, y: event.pageY };
|
|
if (carrier.value && getComputedStyle(carrier.value).opacity !== "0") {
|
|
if (pos.x + 15 + carrier.value.clientWidth <= document.body.scrollWidth) {
|
|
carrier.value.style.left = (pos.x + 15) + "px";
|
|
} else {
|
|
carrier.value.style.left = (document.body.scrollWidth - carrier.value.clientWidth - 5) + "px";
|
|
}
|
|
if (pos.y + carrier.value.clientHeight <= document.body.scrollHeight) {
|
|
carrier.value.style.top = pos.y + "px";
|
|
} else {
|
|
carrier.value.style.top = (document.body.scrollHeight - carrier.value.clientHeight - 5) + "px";
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
watchEffect(() => {
|
|
if (carrier.value) {
|
|
carrier.value.style.height = active.value ? '16px' : '0';
|
|
carrier.value.style.opacity = active.value ? '1' : '0';
|
|
carrier.value.style.width = active.value ? '350px' : '0';
|
|
}
|
|
});
|
|
|
|
return () => <>
|
|
<div class="tooltip-container" {...attrs}
|
|
onMouseenter={() => { active.value = true; }}
|
|
onMouseleave={() => { active.value = false; }}
|
|
>
|
|
{slots.default && <slots.default />}
|
|
</div>
|
|
<div style={carrierStyle} ref={carrier}>
|
|
<span style={textCarrierStyle}>{props.tooltip}</span>
|
|
</div>
|
|
</>;
|
|
},
|
|
});
|