djledda.de main
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.
 
 

81 lines
2.7 KiB

  1. import { watchEffect, watch, onMounted, type CSSProperties, defineComponent, ref } from "vue";
  2. const carrierStyle = {
  3. opacity: "0",
  4. display: "block",
  5. pointerEvents: "none",
  6. backgroundColor: "black",
  7. border: "white solid 1px",
  8. color: "white",
  9. padding: "10px",
  10. position: "absolute",
  11. zIndex: "1",
  12. overflow: "hidden",
  13. height: "0",
  14. width: "0",
  15. transition: "opacity 200ms, height 200ms, width 200ms",
  16. } satisfies CSSProperties;
  17. const textCarrierStyle = {
  18. fontSize: '16px',
  19. fontFamily: "Roboto, serif",
  20. display: "block",
  21. overflow: "hidden",
  22. } satisfies CSSProperties;
  23. const defaultWidth = 350;
  24. export default defineComponent({
  25. name: "dj-sexy-tooltip",
  26. props: {
  27. tooltip: {
  28. type: String,
  29. required: true,
  30. },
  31. },
  32. setup(props, { slots, attrs }) {
  33. const active = ref(false);
  34. const carrier = ref<HTMLElement | null>(null);
  35. const textCarrier = ref<HTMLElement | null>(null);
  36. onMounted(() => {
  37. document.addEventListener("mousemove", (event) => {
  38. const pos = { x: event.pageX, y: event.pageY };
  39. if (carrier.value && getComputedStyle(carrier.value).opacity !== "0") {
  40. if (pos.x + 15 + carrier.value.clientWidth <= document.body.scrollWidth) {
  41. carrier.value.style.left = (pos.x + 15) + "px";
  42. } else {
  43. carrier.value.style.left = (document.body.scrollWidth - carrier.value.clientWidth - 5) + "px";
  44. }
  45. if (pos.y + carrier.value.clientHeight <= document.body.scrollHeight) {
  46. carrier.value.style.top = pos.y + "px";
  47. } else {
  48. carrier.value.style.top = (document.body.scrollHeight - carrier.value.clientHeight - 5) + "px";
  49. }
  50. }
  51. });
  52. });
  53. watchEffect(() => {
  54. if (carrier.value) {
  55. carrier.value.style.height = active.value ? '16px' : '0';
  56. carrier.value.style.opacity = active.value ? '1' : '0';
  57. carrier.value.style.width = active.value ? '350px' : '0';
  58. }
  59. });
  60. return () => <>
  61. <div class="tooltip-container" {...attrs}
  62. onMouseenter={() => { active.value = true; }}
  63. onMouseleave={() => { active.value = false; }}
  64. >
  65. {slots.default && <slots.default />}
  66. </div>
  67. <div style={carrierStyle} ref={carrier}>
  68. <span style={textCarrierStyle}>{props.tooltip}</span>
  69. </div>
  70. </>;
  71. },
  72. });