improving stats page tooltips (click day keeps tooltip open)
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@ input:
|
|||||||
metadata_csv: ~/src/cycling_data_davide/activities.csv
|
metadata_csv: ~/src/cycling_data_davide/activities.csv
|
||||||
|
|
||||||
output:
|
output:
|
||||||
dir: ~/bincio_data
|
dir: ~/src/bincio_data
|
||||||
|
|
||||||
default_privacy: public
|
default_privacy: public
|
||||||
|
|
||||||
|
|||||||
@@ -28,14 +28,15 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
let hoveredDate: string | null = null;
|
let hoveredDate: string | null = null;
|
||||||
|
let pinnedDate: string | null = null;
|
||||||
|
let tooltipEl: HTMLElement | null = null;
|
||||||
let tooltipPos = { x: 0, y: 0 };
|
let tooltipPos = { x: 0, y: 0 };
|
||||||
let hideTimer: ReturnType<typeof setTimeout> | null = null;
|
let hideTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
$: tooltipActivities = hoveredDate ? (activitiesByDate.get(hoveredDate) ?? []) : [];
|
|
||||||
|
|
||||||
function onCellEnter(date: string, e: MouseEvent) {
|
$: tooltipDate = pinnedDate ?? hoveredDate;
|
||||||
if (!date || !activitiesByDate.has(date)) return;
|
$: tooltipActivities = tooltipDate ? (activitiesByDate.get(tooltipDate) ?? []) : [];
|
||||||
if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; }
|
|
||||||
hoveredDate = date;
|
function updatePos(e: MouseEvent) {
|
||||||
const vw = window.innerWidth;
|
const vw = window.innerWidth;
|
||||||
const vh = window.innerHeight;
|
const vh = window.innerHeight;
|
||||||
tooltipPos = {
|
tooltipPos = {
|
||||||
@@ -44,18 +45,49 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCellEnter(date: string, e: MouseEvent) {
|
||||||
|
if (!date || !activitiesByDate.has(date)) return;
|
||||||
|
if (pinnedDate) return;
|
||||||
|
if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; }
|
||||||
|
hoveredDate = date;
|
||||||
|
updatePos(e);
|
||||||
|
}
|
||||||
|
|
||||||
function onCellLeave() {
|
function onCellLeave() {
|
||||||
|
if (pinnedDate) return;
|
||||||
hideTimer = setTimeout(() => { hoveredDate = null; }, 120);
|
hideTimer = setTimeout(() => { hoveredDate = null; }, 120);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCellClick(date: string, e: MouseEvent) {
|
||||||
|
if (!date || !activitiesByDate.has(date)) return;
|
||||||
|
e.stopPropagation();
|
||||||
|
if (pinnedDate === date) {
|
||||||
|
pinnedDate = null;
|
||||||
|
} else {
|
||||||
|
pinnedDate = date;
|
||||||
|
updatePos(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onTooltipEnter() {
|
function onTooltipEnter() {
|
||||||
if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; }
|
if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTooltipLeave() {
|
function onTooltipLeave() {
|
||||||
|
if (pinnedDate) return;
|
||||||
hoveredDate = null;
|
hoveredDate = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onWindowClick(e: MouseEvent) {
|
||||||
|
if (!pinnedDate) return;
|
||||||
|
if (tooltipEl && tooltipEl.contains(e.target as Node)) return;
|
||||||
|
pinnedDate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKeydown(e: KeyboardEvent) {
|
||||||
|
if (e.key === 'Escape') pinnedDate = null;
|
||||||
|
}
|
||||||
|
|
||||||
// ── Heatmap data ─────────────────────────────────────────────────────────
|
// ── Heatmap data ─────────────────────────────────────────────────────────
|
||||||
// byDateBySport: date → sport → total distance (m)
|
// byDateBySport: date → sport → total distance (m)
|
||||||
$: byDateBySport = (() => {
|
$: byDateBySport = (() => {
|
||||||
@@ -269,10 +301,11 @@
|
|||||||
</div>
|
</div>
|
||||||
{#each week as date}
|
{#each week as date}
|
||||||
<div
|
<div
|
||||||
class="w-[10px] h-[10px] rounded-[2px] {date && activitiesByDate.has(date) ? 'cursor-pointer' : ''}"
|
class="w-[10px] h-[10px] rounded-[2px] {date && activitiesByDate.has(date) ? 'cursor-pointer' : ''} {date && date === pinnedDate ? 'ring-1 ring-white ring-offset-[1px] ring-offset-zinc-950' : ''}"
|
||||||
style="background:{cellColors.get(date) ?? '#27272a'}"
|
style="background:{cellColors.get(date) ?? '#27272a'}"
|
||||||
on:mouseenter={e => onCellEnter(date, e)}
|
on:mouseenter={e => onCellEnter(date, e)}
|
||||||
on:mouseleave={onCellLeave}
|
on:mouseleave={onCellLeave}
|
||||||
|
on:click={e => onCellClick(date, e)}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@@ -306,17 +339,29 @@
|
|||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<svelte:window on:click={onWindowClick} on:keydown={onKeydown} />
|
||||||
|
|
||||||
<!-- Day tooltip -->
|
<!-- Day tooltip -->
|
||||||
{#if hoveredDate && tooltipActivities.length > 0}
|
{#if tooltipDate && tooltipActivities.length > 0}
|
||||||
<div
|
<div
|
||||||
|
bind:this={tooltipEl}
|
||||||
class="fixed z-50 bg-zinc-900 border border-zinc-700 rounded-xl shadow-2xl p-3 w-[280px]"
|
class="fixed z-50 bg-zinc-900 border border-zinc-700 rounded-xl shadow-2xl p-3 w-[280px]"
|
||||||
style="left:{tooltipPos.x}px; top:{tooltipPos.y}px"
|
style="left:{tooltipPos.x}px; top:{tooltipPos.y}px"
|
||||||
on:mouseenter={onTooltipEnter}
|
on:mouseenter={onTooltipEnter}
|
||||||
on:mouseleave={onTooltipLeave}
|
on:mouseleave={onTooltipLeave}
|
||||||
>
|
>
|
||||||
<p class="text-xs font-medium text-zinc-400 mb-2">
|
<div class="flex items-center justify-between mb-2">
|
||||||
{new Date(hoveredDate + 'T12:00:00').toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' })}
|
<p class="text-xs font-medium text-zinc-400">
|
||||||
|
{new Date(tooltipDate + 'T12:00:00').toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' })}
|
||||||
</p>
|
</p>
|
||||||
|
{#if pinnedDate}
|
||||||
|
<button
|
||||||
|
class="text-zinc-500 hover:text-zinc-300 transition-colors text-sm leading-none ml-2"
|
||||||
|
on:click|stopPropagation={() => pinnedDate = null}
|
||||||
|
aria-label="Close"
|
||||||
|
>✕</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
{#each tooltipActivities as a}
|
{#each tooltipActivities as a}
|
||||||
<a
|
<a
|
||||||
|
|||||||
Reference in New Issue
Block a user