Fixed progress bar overflow with floating tooltip action

This commit is contained in:
2026-05-08 17:35:34 +02:00
parent 1af46c0fa3
commit 267b174931
2 changed files with 75 additions and 41 deletions
+29
View File
@@ -27,3 +27,32 @@ body {
margin: 0; margin: 0;
min-height: 100svh; min-height: 100svh;
} }
.tooltip-floating {
position: fixed;
z-index: 9999;
background: var(--surface);
color: var(--text);
border: 1px solid var(--border);
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
font-family: var(--sans);
font-size: 0.85rem;
font-weight: 400;
white-space: nowrap;
padding: 0.45em 0.9em;
border-radius: 8px;
pointer-events: none;
opacity: 0;
transform: translateY(4px);
transition: opacity 0.15s ease, transform 0.15s ease;
}
.tooltip-floating::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: var(--border);
}
+45 -40
View File
@@ -6,6 +6,44 @@
import { enqueue } from '$lib/download-pool.js'; import { enqueue } from '$lib/download-pool.js';
import type { Station, Measurement } from '$lib/types.js'; import type { Station, Measurement } from '$lib/types.js';
function floatingTooltip(node: HTMLElement, text: string) {
let el: HTMLDivElement | null = null;
function show() {
if (!text) return;
const rect = node.getBoundingClientRect();
el = document.createElement('div');
el.className = 'tooltip-floating';
el.textContent = text;
document.body.appendChild(el);
el.style.top = `${rect.top - el.offsetHeight - 10}px`;
el.style.left = `${rect.left + rect.width / 2 - el.offsetWidth / 2}px`;
void el.offsetHeight; // force reflow prima della transizione
el.style.opacity = '1';
el.style.transform = 'translateY(0)';
}
function hide() {
if (!el) return;
const target = el;
el = null;
target.style.opacity = '0';
target.style.transform = 'translateY(4px)';
target.addEventListener('transitionend', () => target.remove(), { once: true });
}
node.addEventListener('mouseenter', show);
node.addEventListener('mouseleave', hide);
return {
update(t: string) { text = t; },
destroy() {
node.removeEventListener('mouseenter', show);
node.removeEventListener('mouseleave', hide);
hide();
},
};
}
let { station }: { station: Station } = $props(); let { station }: { station: Station } = $props();
const formatDate = (d: string) => new Intl.DateTimeFormat('it-IT', { const formatDate = (d: string) => new Intl.DateTimeFormat('it-IT', {
@@ -99,12 +137,12 @@
<div class="right"> <div class="right">
<span class="date">Attivata il {createdDate}</span> <span class="date">Attivata il {createdDate}</span>
<span class="sep">·</span> <span class="sep">·</span>
<span class="status" class:active={isActive} class:ended={!isActive}> <span
{isActive ? 'Attiva' : 'Terminata'} class="status"
{#if !isActive} class:active={isActive}
<span class="tooltip">Terminata il {endDate}</span> class:ended={!isActive}
{/if} use:floatingTooltip={!isActive ? `Terminata il ${endDate}` : ''}
</span> >{isActive ? 'Attiva' : 'Terminata'}</span>
<button <button
type="button" type="button"
@@ -153,6 +191,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 1.25rem; gap: 1.25rem;
overflow: hidden;
} }
button { button {
@@ -272,39 +311,6 @@
color: var(--text-dim); color: var(--text-dim);
} }
.tooltip {
position: absolute;
bottom: calc(100% + 16px);
left: 50%;
transform: translateX(-50%);
background: var(--surface);
color: var(--text);
border: 1px solid var(--border);
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
font-size: 0.85rem;
font-weight: 400;
white-space: nowrap;
padding: 0.45em 0.9em;
border-radius: 8px;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
}
.status:hover .tooltip {
opacity: 1;
}
.tooltip::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: var(--border);
}
.bar-wrap { .bar-wrap {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
@@ -312,7 +318,6 @@
right: 0; right: 0;
height: 3px; height: 3px;
background: var(--border); background: var(--border);
border-radius: 0 0 14px 14px;
overflow: hidden; overflow: hidden;
} }