feat: open model details modal on hover and refine cards layout
- Add on-hover modal opening for model cards with debounce - Keep click-to-open behavior as fallback - Prevent accidental hover triggers while moving inside same card - Convert models list to responsive grid layout - Improve card visual feedback and helper text for interaction
This commit is contained in:
@@ -7,6 +7,8 @@ class LLMMonitorApp {
|
||||
constructor() {
|
||||
this.worker = null;
|
||||
this.selectedModelName = null;
|
||||
this.hoverOpenDelayMs = 180;
|
||||
this.hoverOpenTimer = null;
|
||||
this.lastData = {
|
||||
health: null,
|
||||
models: null
|
||||
@@ -50,6 +52,49 @@ class LLMMonitorApp {
|
||||
this.showModelDetails(decodeURIComponent(modelKey));
|
||||
});
|
||||
|
||||
// Apertura modal on-hover (con piccolo delay per evitare aperture involontarie)
|
||||
document.getElementById("models-container")?.addEventListener("mouseover", (event) => {
|
||||
const card = event.target.closest("[data-model-key]");
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Evita trigger quando il mouse si muove dentro la stessa card
|
||||
if (event.relatedTarget && card.contains(event.relatedTarget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const modelKey = card.getAttribute("data-model-key");
|
||||
if (!modelKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.hoverOpenTimer) {
|
||||
clearTimeout(this.hoverOpenTimer);
|
||||
}
|
||||
|
||||
this.hoverOpenTimer = setTimeout(() => {
|
||||
this.showModelDetails(decodeURIComponent(modelKey));
|
||||
}, this.hoverOpenDelayMs);
|
||||
});
|
||||
|
||||
document.getElementById("models-container")?.addEventListener("mouseout", (event) => {
|
||||
const card = event.target.closest("[data-model-key]");
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Non cancellare se si resta all'interno della stessa card
|
||||
if (event.relatedTarget && card.contains(event.relatedTarget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.hoverOpenTimer) {
|
||||
clearTimeout(this.hoverOpenTimer);
|
||||
this.hoverOpenTimer = null;
|
||||
}
|
||||
});
|
||||
|
||||
// Chiusura modal con pulsante X
|
||||
document.getElementById("model-details-close")?.addEventListener("click", () => {
|
||||
this.hideModelDetails();
|
||||
@@ -187,7 +232,7 @@ class LLMMonitorApp {
|
||||
const modelName = this.escapeHtml(model.name);
|
||||
const modelKey = encodeURIComponent(model.name);
|
||||
return `
|
||||
<div data-model-key="${modelKey}" class="bg-gray-700 rounded-lg p-4 border border-gray-600 hover:border-purple-500 transition cursor-pointer">
|
||||
<div data-model-key="${modelKey}" class="bg-gray-700 rounded-lg p-4 border border-gray-600 hover:border-purple-500 hover:-translate-y-0.5 transition cursor-pointer h-full">
|
||||
<div class="flex items-start justify-between mb-3">
|
||||
<h3 class="text-lg font-semibold">${modelName}</h3>
|
||||
<span class="bg-purple-600 px-3 py-1 rounded text-xs font-medium">Caricato</span>
|
||||
@@ -206,7 +251,7 @@ class LLMMonitorApp {
|
||||
<p class="text-gray-400 text-xs">Digest</p>
|
||||
<p class="font-mono text-xs bg-gray-800 p-2 rounded mt-1 break-all">${this.escapeHtml(model.digest.substring(0, 64))}...</p>
|
||||
</div>
|
||||
<p class="text-xs text-purple-300 mt-3">Clicca per vedere dettagli show</p>
|
||||
<p class="text-xs text-purple-300 mt-3">Passa il mouse o clicca per vedere dettagli show</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -60,14 +60,17 @@
|
||||
<!-- Models Section -->
|
||||
<div class="bg-gray-800 rounded-lg border border-gray-700 p-6">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h2 class="text-xl font-bold">Modelli Disponibili</h2>
|
||||
<div>
|
||||
<h2 class="text-xl font-bold">Modelli Disponibili</h2>
|
||||
<p class="text-xs text-gray-400 mt-1">Passa il mouse o clicca una card per aprire la modal dettagli.</p>
|
||||
</div>
|
||||
<button id="refresh-btn" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded-lg text-sm font-medium transition">
|
||||
🔄 Aggiorna
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Models List -->
|
||||
<div id="models-container" class="space-y-4">
|
||||
<div id="models-container" class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
|
||||
<div class="text-center py-8">
|
||||
<div class="animate-spin inline-block w-8 h-8 border-4 border-gray-600 border-t-purple-500 rounded-full"></div>
|
||||
<p class="text-gray-400 mt-4">Caricamento modelli...</p>
|
||||
|
||||
Reference in New Issue
Block a user