Skip to content

Commit a30900a

Browse files
authored
Hover tooltips (#427)
* hover tool tips added Signed-off-by: Keval Mahajan <[email protected]> * minor linting fix Signed-off-by: Keval Mahajan <[email protected]> * tool tip disappears when test is clicked Signed-off-by: Keval Mahajan <[email protected]> * linting Signed-off-by: Keval Mahajan <[email protected]> --------- Signed-off-by: Keval Mahajan <[email protected]>
1 parent 412622e commit a30900a

File tree

3 files changed

+187
-35
lines changed

3 files changed

+187
-35
lines changed

mcpgateway/static/admin.css

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
border: 1px solid #ebccd1;
99
}
1010

11-
1211
/* CSS for the spinner */
1312
.spinner {
1413
border: 4px solid #f3f3f3;
@@ -29,6 +28,26 @@
2928
/* Ensures it behaves like a block-level element */
3029
}
3130

31+
/* CSS for the tooltip */
32+
.tooltip {
33+
position: fixed;
34+
z-index: 9999;
35+
background-color: #1f2937; /* Tailwind's gray-800 */
36+
color: white;
37+
font-size: 0.875rem; /* text-sm */
38+
border-radius: 0.5rem; /* Increased rounded corners */
39+
padding: 0.75rem 1rem; /* More padding */
40+
pointer-events: none;
41+
transition: transform 0.2s ease, opacity 0.3s ease; /* Added smooth transition */
42+
opacity: 0;
43+
transform: scale(0.8); /* Tooltip starts slightly smaller */
44+
}
45+
46+
.tooltip.show {
47+
opacity: 1;
48+
transform: scale(1); /* Scales up smoothly */
49+
}
50+
3251
@keyframes spin {
3352
0% {
3453
transform: rotate(0deg);

mcpgateway/static/admin.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4086,6 +4086,104 @@ if (window.performance && window.performance.mark) {
40864086
console.log("✓ Performance markers available");
40874087
}
40884088

4089+
// ===================================================================
4090+
// Tool Tips for components with Alpine.js
4091+
// ===================================================================
4092+
4093+
/* global Alpine */
4094+
function setupTooltipsWithAlpine() {
4095+
document.addEventListener("alpine:init", () => {
4096+
console.log("Initializing Alpine tooltip directive...");
4097+
4098+
Alpine.directive("tooltip", (el, { expression }, { evaluate }) => {
4099+
let tooltipEl = null;
4100+
4101+
const moveTooltip = (e) => {
4102+
if (!tooltipEl) {
4103+
return;
4104+
}
4105+
4106+
const paddingX = 12;
4107+
const paddingY = 20;
4108+
const tipRect = tooltipEl.getBoundingClientRect();
4109+
4110+
let left = e.clientX + paddingX;
4111+
let top = e.clientY + paddingY;
4112+
4113+
if (left + tipRect.width > window.innerWidth - 8) {
4114+
left = e.clientX - tipRect.width - paddingX;
4115+
}
4116+
if (top + tipRect.height > window.innerHeight - 8) {
4117+
top = e.clientY - tipRect.height - paddingY;
4118+
}
4119+
4120+
tooltipEl.style.left = `${left}px`;
4121+
tooltipEl.style.top = `${top}px`;
4122+
};
4123+
4124+
const showTooltip = (event) => {
4125+
const text = evaluate(expression);
4126+
if (!text) {
4127+
return;
4128+
}
4129+
4130+
hideTooltip(); // Clean up any existing tooltip
4131+
4132+
tooltipEl = document.createElement("div");
4133+
tooltipEl.textContent = text;
4134+
tooltipEl.setAttribute("role", "tooltip");
4135+
tooltipEl.className =
4136+
"fixed z-50 max-w-xs px-3 py-2 text-sm text-white bg-black/80 rounded-lg shadow-lg pointer-events-none opacity-0 transition-opacity duration-200";
4137+
4138+
document.body.appendChild(tooltipEl);
4139+
4140+
if (event?.clientX && event?.clientY) {
4141+
moveTooltip(event);
4142+
el.addEventListener("mousemove", moveTooltip);
4143+
} else {
4144+
const rect = el.getBoundingClientRect();
4145+
const scrollY = window.scrollY || window.pageYOffset;
4146+
const scrollX = window.scrollX || window.pageXOffset;
4147+
tooltipEl.style.left = `${rect.left + scrollX}px`;
4148+
tooltipEl.style.top = `${rect.bottom + scrollY + 10}px`;
4149+
}
4150+
4151+
requestAnimationFrame(() => {
4152+
tooltipEl.style.opacity = "1";
4153+
});
4154+
window.addEventListener("scroll", hideTooltip, {
4155+
passive: true,
4156+
});
4157+
window.addEventListener("resize", hideTooltip, {
4158+
passive: true,
4159+
});
4160+
};
4161+
4162+
const hideTooltip = () => {
4163+
if (!tooltipEl) {
4164+
return;
4165+
}
4166+
4167+
tooltipEl.style.opacity = "0";
4168+
el.removeEventListener("mousemove", moveTooltip);
4169+
window.removeEventListener("scroll", hideTooltip);
4170+
window.removeEventListener("resize", hideTooltip);
4171+
el.addEventListener("click", hideTooltip);
4172+
const toRemove = tooltipEl;
4173+
tooltipEl = null;
4174+
setTimeout(() => toRemove.remove(), 200);
4175+
};
4176+
el.addEventListener("mouseenter", showTooltip);
4177+
el.addEventListener("mouseleave", hideTooltip);
4178+
el.addEventListener("focus", showTooltip);
4179+
el.addEventListener("blur", hideTooltip);
4180+
el.addEventListener("click", hideTooltip);
4181+
});
4182+
});
4183+
}
4184+
4185+
setupTooltipsWithAlpine();
4186+
40894187
// ===================================================================
40904188
// SINGLE CONSOLIDATED INITIALIZATION SYSTEM
40914189
// ===================================================================
@@ -4094,6 +4192,8 @@ document.addEventListener("DOMContentLoaded", () => {
40944192
console.log("🔐 DOM loaded - initializing secure admin interface...");
40954193

40964194
try {
4195+
// initializeTooltips();
4196+
40974197
// 1. Initialize CodeMirror editors first
40984198
initializeCodeMirrorEditors();
40994199

0 commit comments

Comments
 (0)