mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-11-03 20:34:20 +01:00 
			
		
		
		
	fix: Move Tooltip as vue component
This commit is contained in:
		
							
								
								
									
										88
									
								
								packages/mermaid/src/docs/.vitepress/theme/Tooltip.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								packages/mermaid/src/docs/.vitepress/theme/Tooltip.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div
 | 
			
		||||
    v-if="isVisible"
 | 
			
		||||
    class="mermaid-chart-tooltip"
 | 
			
		||||
    :class="{ visible: isVisible }"
 | 
			
		||||
    :style="tooltipStyle"
 | 
			
		||||
  >
 | 
			
		||||
    <span class="mdi mdi-open-in-new"></span>
 | 
			
		||||
    Opens in MermaidChart.com
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ref, onMounted, onUnmounted } from 'vue';
 | 
			
		||||
 | 
			
		||||
const isVisible = ref(false);
 | 
			
		||||
const currentTarget = ref<HTMLElement | null>(null);
 | 
			
		||||
const tooltipStyle = ref({});
 | 
			
		||||
 | 
			
		||||
const showTooltip = (target: HTMLElement) => {
 | 
			
		||||
  currentTarget.value = target;
 | 
			
		||||
  const rect = target.getBoundingClientRect();
 | 
			
		||||
  tooltipStyle.value = {
 | 
			
		||||
    left: `${rect.left + rect.width / 2}px`,
 | 
			
		||||
    top: `${rect.top}px`,
 | 
			
		||||
  };
 | 
			
		||||
  isVisible.value = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const hideTooltip = () => {
 | 
			
		||||
  currentTarget.value = null;
 | 
			
		||||
  isVisible.value = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handleMouseOver = (e: MouseEvent) => {
 | 
			
		||||
  const target = e.target as HTMLElement;
 | 
			
		||||
  if (
 | 
			
		||||
    target.matches('a[href*="mermaidchart.com"]') ||
 | 
			
		||||
    target.matches('button[onclick*="mermaidchart.com"]')
 | 
			
		||||
  ) {
 | 
			
		||||
    showTooltip(target);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handleMouseOut = (e: MouseEvent) => {
 | 
			
		||||
  if (!currentTarget.value?.contains(e.relatedTarget as HTMLElement)) {
 | 
			
		||||
    hideTooltip();
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  document.addEventListener('mouseover', handleMouseOver);
 | 
			
		||||
  document.addEventListener('mouseout', handleMouseOut);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onUnmounted(() => {
 | 
			
		||||
  document.removeEventListener('mouseover', handleMouseOver);
 | 
			
		||||
  document.removeEventListener('mouseout', handleMouseOut);
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.mermaid-chart-tooltip {
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  background: black;
 | 
			
		||||
  color: white;
 | 
			
		||||
  padding: 0.3rem 0.6rem;
 | 
			
		||||
  border-radius: 0.5rem;
 | 
			
		||||
  font-size: 1rem;
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
  z-index: 1000;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  transition:
 | 
			
		||||
    opacity 0.3s ease,
 | 
			
		||||
    transform 0.3s ease;
 | 
			
		||||
  transform: translate(-50%, -90%);
 | 
			
		||||
  margin-top: -0.5rem;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  gap: 0.375rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mermaid-chart-tooltip.visible {
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
  transform: translate(-50%, -100%);
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,13 +1,10 @@
 | 
			
		||||
/* eslint-disable no-console */
 | 
			
		||||
import DefaultTheme from 'vitepress/theme';
 | 
			
		||||
import './custom.css';
 | 
			
		||||
// @ts-ignore Type not available
 | 
			
		||||
import Mermaid from './Mermaid.vue';
 | 
			
		||||
// @ts-ignore Type not available
 | 
			
		||||
import Tooltip from './Tooltip.vue';
 | 
			
		||||
import Contributors from '../components/Contributors.vue';
 | 
			
		||||
// @ts-ignore Type not available
 | 
			
		||||
import HomePage from '../components/HomePage.vue';
 | 
			
		||||
// @ts-ignore Type not available
 | 
			
		||||
import TopBar from '../components/TopBar.vue';
 | 
			
		||||
import { getRedirect } from './redirect.js';
 | 
			
		||||
// @ts-ignore Type not available
 | 
			
		||||
@@ -17,89 +14,14 @@ import Theme from 'vitepress/theme';
 | 
			
		||||
import { h } from 'vue';
 | 
			
		||||
import '../style/main.css';
 | 
			
		||||
 | 
			
		||||
// Add tooltips to Mermaid Chart buttons
 | 
			
		||||
const addMermaidChartTooltips = () => {
 | 
			
		||||
  const tooltipStyle = document.createElement('style');
 | 
			
		||||
  tooltipStyle.textContent = `
 | 
			
		||||
    .mermaid-chart-tooltip {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      background: black;
 | 
			
		||||
      color: white;
 | 
			
		||||
      padding: 0.3rem 0.6rem;
 | 
			
		||||
      border-radius: 0.5rem;
 | 
			
		||||
      font-size: 1rem;
 | 
			
		||||
      pointer-events: none;
 | 
			
		||||
      z-index: 1000;
 | 
			
		||||
      max-width: 20rem;
 | 
			
		||||
      text-align: center;
 | 
			
		||||
      opacity: 0;
 | 
			
		||||
      transition: opacity 0.3s ease, transform 0.3s ease;
 | 
			
		||||
      transform: translateY(-90%);
 | 
			
		||||
      margin-top: -0.5rem;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      gap: 0.375rem;
 | 
			
		||||
    }
 | 
			
		||||
    .mermaid-chart-tooltip.visible {
 | 
			
		||||
      opacity: 1;
 | 
			
		||||
      transform: translateY(-100%);
 | 
			
		||||
    }
 | 
			
		||||
    .mermaid-chart-tooltip svg {
 | 
			
		||||
      width: 1.25rem;
 | 
			
		||||
      height: 1.25rem;
 | 
			
		||||
      fill: currentColor;
 | 
			
		||||
    }
 | 
			
		||||
  `;
 | 
			
		||||
  document.head.appendChild(tooltipStyle);
 | 
			
		||||
 | 
			
		||||
  const tooltip = document.createElement('div');
 | 
			
		||||
  tooltip.className = 'mermaid-chart-tooltip';
 | 
			
		||||
  document.body.appendChild(tooltip);
 | 
			
		||||
 | 
			
		||||
  let currentTarget: HTMLElement | null = null;
 | 
			
		||||
 | 
			
		||||
  const showTooltip = (target: HTMLElement) => {
 | 
			
		||||
    currentTarget = target;
 | 
			
		||||
    const rect = target.getBoundingClientRect();
 | 
			
		||||
    tooltip.innerHTML = `
 | 
			
		||||
      <span class="mdi mdi-open-in-new"></span>
 | 
			
		||||
      Opens in MermaidChart.com
 | 
			
		||||
    `;
 | 
			
		||||
    tooltip.style.left = rect.left + rect.width / 2 - tooltip.offsetWidth / 2 + 'px';
 | 
			
		||||
    tooltip.style.top = rect.top + 'px';
 | 
			
		||||
    tooltip.classList.add('visible');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const hideTooltip = () => {
 | 
			
		||||
    currentTarget = null;
 | 
			
		||||
    tooltip.classList.remove('visible');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  document.addEventListener('mouseover', (e) => {
 | 
			
		||||
    const target = e.target as HTMLElement;
 | 
			
		||||
    if (
 | 
			
		||||
      target.matches('a[href*="mermaidchart.com"]') ||
 | 
			
		||||
      target.matches('button[onclick*="mermaidchart.com"]')
 | 
			
		||||
    ) {
 | 
			
		||||
      showTooltip(target);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  document.addEventListener('mouseout', (e) => {
 | 
			
		||||
    if (!currentTarget?.contains(e.relatedTarget as HTMLElement)) {
 | 
			
		||||
      hideTooltip();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  ...DefaultTheme,
 | 
			
		||||
  Layout() {
 | 
			
		||||
    return h(Theme.Layout, null, {
 | 
			
		||||
      // Keeping this as comment as it took a lot of time to figure out how to add a component to the top bar.
 | 
			
		||||
      'home-hero-before': () => h(TopBar),
 | 
			
		||||
      'home-features-after': () => h(HomePage),
 | 
			
		||||
      'home-hero-before': () => h(TopBar),
 | 
			
		||||
      'doc-before': () => h(TopBar),
 | 
			
		||||
      'layout-bottom': () => h(Tooltip),
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  enhanceApp({ app, router }: EnhanceAppContext) {
 | 
			
		||||
@@ -107,13 +29,6 @@ export default {
 | 
			
		||||
    app.component('Mermaid', Mermaid);
 | 
			
		||||
    app.component('Contributors', Contributors);
 | 
			
		||||
 | 
			
		||||
    // Add tooltips after app is mounted
 | 
			
		||||
    app.mixin({
 | 
			
		||||
      mounted() {
 | 
			
		||||
        addMermaidChartTooltips();
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    router.onBeforeRouteChange = (to) => {
 | 
			
		||||
      try {
 | 
			
		||||
        const url = new URL(window.location.origin + to);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user