fix: Move Tooltip as vue component

This commit is contained in:
Sidharth Vinod
2025-04-09 15:50:27 +05:30
parent 9a90aca8e6
commit a3cf9de01b
2 changed files with 91 additions and 88 deletions

View 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>

View File

@@ -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);