Optime tooltips display

This commit is contained in:
yangdx
2025-03-27 16:50:27 +08:00
parent 4fae0fa54e
commit 441d1b8ced

View File

@@ -47,18 +47,41 @@ const getDisplayFileName = (doc: DocStatusResponse, maxLength: number = 20): str
}; };
const pulseStyle = ` const pulseStyle = `
/* Fixed tooltip styles for small tables */ /* Tooltip styles */
.tooltip-fixed {
position: fixed !important;
z-index: 9999 !important;
}
/* Parent container for tooltips */
.tooltip-container { .tooltip-container {
position: relative; position: relative;
overflow: visible !important; 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 { @keyframes pulse {
0% { 0% {
background-color: rgb(255 0 0 / 0.1); background-color: rgb(255 0 0 / 0.1);
@@ -180,64 +203,47 @@ export default function DocumentManager() {
// Reference to the card content element // Reference to the card content element
const cardContentRef = useRef<HTMLDivElement>(null); const cardContentRef = useRef<HTMLDivElement>(null);
// Add tooltip position adjustment based on mouse position // Add tooltip position adjustment for fixed positioning
useEffect(() => { useEffect(() => {
if (!docs) return; if (!docs) return;
// Function to handle mouse movement - throttled to reduce layout calculations // Function to position tooltips
let lastExecution = 0; const positionTooltips = () => {
const throttleInterval = 50; // ms // Get all tooltip containers
const containers = document.querySelectorAll<HTMLElement>('.tooltip-container');
const handleMouseMove = () => { containers.forEach(container => {
const now = Date.now(); const tooltip = container.querySelector<HTMLElement>('.tooltip');
if (now - lastExecution < throttleInterval) return; if (!tooltip) return;
lastExecution = now;
const cardContent = cardContentRef.current; // Only position visible tooltips
if (!cardContent) return; if (getComputedStyle(tooltip).visibility === 'hidden') return;
// Get all visible tooltips // Get container position
const visibleTooltips = document.querySelectorAll<HTMLElement>('.group:hover > div[class*="invisible group-hover:visible absolute"]'); const rect = container.getBoundingClientRect();
if (visibleTooltips.length === 0) return;
visibleTooltips.forEach(tooltip => { // Position tooltip above the container
// Get the parent element that triggered the tooltip tooltip.style.left = `${rect.left}px`;
const triggerElement = tooltip.parentElement; tooltip.style.top = `${rect.top - 5}px`;
if (!triggerElement) return; tooltip.style.transform = 'translateY(-100%)';
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';
}); });
}; };
// Add mouse move listener to the document // Set up event listeners
document.addEventListener('mousemove', handleMouseMove); 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 () => { return () => {
document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseover', handleMouseOver);
}; };
}, [docs]); }, [docs]);
@@ -395,7 +401,7 @@ export default function DocumentManager() {
)} )}
{docs && ( {docs && (
<div className="absolute inset-0 flex flex-col p-0"> <div className="absolute inset-0 flex flex-col p-0">
<div className="w-full h-full flex flex-col border border-gray-200 dark:border-gray-700 overflow-auto"> <div className="w-full h-full flex flex-col border border-gray-200 dark:border-gray-700 overflow-hidden">
<Table className="w-full"> <Table className="w-full">
<TableHeader className="sticky top-0 bg-background z-10 shadow-sm"> <TableHeader className="sticky top-0 bg-background z-10 shadow-sm">
<TableRow className="border-b bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/75 shadow-[inset_0_-1px_0_rgba(0,0,0,0.1)]"> <TableRow className="border-b bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/75 shadow-[inset_0_-1px_0_rgba(0,0,0,0.1)]">
@@ -458,7 +464,7 @@ export default function DocumentManager() {
<div className="truncate"> <div className="truncate">
{getDisplayFileName(doc, 30)} {getDisplayFileName(doc, 30)}
</div> </div>
<div className="invisible group-hover:visible absolute z-[9999] mt-1 max-w-[600px] whitespace-normal break-all rounded-md bg-black/95 px-3 py-2 text-sm text-white shadow-lg dark:bg-white/95 dark:text-black"> <div className="invisible group-hover:visible tooltip">
{doc.file_path} {doc.file_path}
</div> </div>
</div> </div>
@@ -469,7 +475,7 @@ export default function DocumentManager() {
<div className="truncate"> <div className="truncate">
{doc.id} {doc.id}
</div> </div>
<div className="invisible group-hover:visible absolute z-[9999] mt-1 max-w-[600px] whitespace-normal break-all rounded-md bg-black/95 px-3 py-2 text-sm text-white shadow-lg dark:bg-white/95 dark:text-black"> <div className="invisible group-hover:visible tooltip">
{doc.file_path} {doc.file_path}
</div> </div>
</div> </div>
@@ -480,7 +486,7 @@ export default function DocumentManager() {
<div className="truncate"> <div className="truncate">
{doc.content_summary} {doc.content_summary}
</div> </div>
<div className="invisible group-hover:visible absolute z-[9999] mt-1 max-w-[600px] whitespace-normal break-all rounded-md bg-black/95 px-3 py-2 text-sm text-white shadow-lg dark:bg-white/95 dark:text-black"> <div className="invisible group-hover:visible tooltip">
{doc.content_summary} {doc.content_summary}
</div> </div>
</div> </div>