From 441d1b8cedc822a6d20e759f48c75cde2bb2958d Mon Sep 17 00:00:00 2001 From: yangdx Date: Thu, 27 Mar 2025 16:50:27 +0800 Subject: [PATCH] Optime tooltips display --- .../src/features/DocumentManager.tsx | 130 +++++++++--------- 1 file changed, 68 insertions(+), 62 deletions(-) diff --git a/lightrag_webui/src/features/DocumentManager.tsx b/lightrag_webui/src/features/DocumentManager.tsx index fd403ef9..612cf5c8 100644 --- a/lightrag_webui/src/features/DocumentManager.tsx +++ b/lightrag_webui/src/features/DocumentManager.tsx @@ -47,18 +47,41 @@ const getDisplayFileName = (doc: DocStatusResponse, maxLength: number = 20): str }; const pulseStyle = ` -/* Fixed tooltip styles for small tables */ -.tooltip-fixed { - position: fixed !important; - z-index: 9999 !important; -} - -/* Parent container for tooltips */ +/* Tooltip styles */ .tooltip-container { position: relative; overflow: visible !important; } +.tooltip { + position: fixed; /* Use fixed positioning to escape overflow constraints */ + z-index: 9999; /* Ensure tooltip appears above all other elements */ + max-width: 600px; + white-space: normal; + border-radius: 0.375rem; + padding: 0.5rem 0.75rem; + background-color: rgba(0, 0, 0, 0.95); + color: white; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + pointer-events: none; /* Prevent tooltip from interfering with mouse events */ +} + +.dark .tooltip { + background-color: rgba(255, 255, 255, 0.95); + color: black; +} + +/* Position tooltip helper class */ +.tooltip-helper { + position: absolute; + visibility: hidden; + pointer-events: none; + top: 0; + left: 0; + width: 100%; + height: 0; +} + @keyframes pulse { 0% { background-color: rgb(255 0 0 / 0.1); @@ -180,64 +203,47 @@ export default function DocumentManager() { // Reference to the card content element const cardContentRef = useRef(null); - // Add tooltip position adjustment based on mouse position + // Add tooltip position adjustment for fixed positioning useEffect(() => { if (!docs) return; - // Function to handle mouse movement - throttled to reduce layout calculations - let lastExecution = 0; - const throttleInterval = 50; // ms - - const handleMouseMove = () => { - const now = Date.now(); - if (now - lastExecution < throttleInterval) return; - lastExecution = now; - - const cardContent = cardContentRef.current; - if (!cardContent) return; - - // Get all visible tooltips - const visibleTooltips = document.querySelectorAll('.group:hover > div[class*="invisible group-hover:visible absolute"]'); - if (visibleTooltips.length === 0) return; - - visibleTooltips.forEach(tooltip => { - // Get the parent element that triggered the tooltip - const triggerElement = tooltip.parentElement; - if (!triggerElement) return; - - const triggerRect = triggerElement.getBoundingClientRect(); - - // Use fixed positioning for all tooltips - tooltip.classList.add('tooltip-fixed'); - - // Calculate position based on trigger element - const tooltipHeight = tooltip.offsetHeight; - const viewportHeight = window.innerHeight; - - // Check if tooltip would go off the bottom of the viewport - const wouldOverflowBottom = triggerRect.bottom + tooltipHeight + 5 > viewportHeight; - - if (wouldOverflowBottom) { - // Position above the trigger - tooltip.style.top = `${triggerRect.top - tooltipHeight - 5}px`; - tooltip.style.bottom = 'auto'; - } else { - // Position below the trigger - tooltip.style.top = `${triggerRect.bottom + 5}px`; - tooltip.style.bottom = 'auto'; - } - - // Horizontal positioning - tooltip.style.left = `${triggerRect.left}px`; - tooltip.style.maxWidth = '600px'; + // Function to position tooltips + const positionTooltips = () => { + // Get all tooltip containers + const containers = document.querySelectorAll('.tooltip-container'); + + containers.forEach(container => { + const tooltip = container.querySelector('.tooltip'); + if (!tooltip) return; + + // Only position visible tooltips + if (getComputedStyle(tooltip).visibility === 'hidden') return; + + // Get container position + const rect = container.getBoundingClientRect(); + + // Position tooltip above the container + tooltip.style.left = `${rect.left}px`; + tooltip.style.top = `${rect.top - 5}px`; + tooltip.style.transform = 'translateY(-100%)'; }); }; - // Add mouse move listener to the document - document.addEventListener('mousemove', handleMouseMove); - + // Set up event listeners + const handleMouseOver = (e: MouseEvent) => { + // Check if target or its parent is a tooltip container + const target = e.target as HTMLElement; + const container = target.closest('.tooltip-container'); + if (!container) return; + + // Small delay to ensure tooltip is visible before positioning + setTimeout(positionTooltips, 10); + }; + + document.addEventListener('mouseover', handleMouseOver); + return () => { - document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseover', handleMouseOver); }; }, [docs]); @@ -395,7 +401,7 @@ export default function DocumentManager() { )} {docs && (
-
+
@@ -458,7 +464,7 @@ export default function DocumentManager() {
{getDisplayFileName(doc, 30)}
-
+
{doc.file_path}
@@ -469,7 +475,7 @@ export default function DocumentManager() {
{doc.id}
-
+
{doc.file_path}
@@ -480,7 +486,7 @@ export default function DocumentManager() {
{doc.content_summary}
-
+
{doc.content_summary}