Fix share-link serialization and tooltip positioning

This commit is contained in:
Codex Agent
2026-03-08 19:44:30 +00:00
parent 02b9c2411f
commit cf1114e8d8

View File

@@ -15,7 +15,7 @@
let val2 = '';
let val3 = '';
let activeField: 1 | 2 | 3 = 1;
let swapState: { originalField: 1 | 2; originalValue: string } | null = null;
let swapState: { originalField: 1 | 2; originalValue: string | number | null } | null = null;
let copyStatus: 'idle' | 'copied' | 'failed' = 'idle';
let statusTimeout: ReturnType<typeof setTimeout> | null = null;
let tooltipFadeTimeout: ReturnType<typeof setTimeout> | null = null;
@@ -23,6 +23,8 @@
let showCopyTooltip = false;
let isTooltipFading = false;
let showHoverTooltip = false;
let footerControlsEl: HTMLDivElement | null = null;
let tooltipX = 20;
let copyStatusMessage = '';
$: has3 = ['3col', '3col-mul'].includes(config.type) || !!config.labels.in3;
@@ -75,21 +77,27 @@
function buildShareUrl() {
const params = new URLSearchParams();
if (val1.trim()) {
params.set('v1', val1);
}
if (val2.trim()) {
params.set('v2', val2);
}
if (val3.trim() && has3) {
params.set('v3', val3);
}
const v1 = toQueryValue(val1);
const v2 = toQueryValue(val2);
const v3 = toQueryValue(val3);
if (v1 !== null) params.set('v1', v1);
if (v2 !== null) params.set('v2', v2);
if (has3 && v3 !== null) params.set('v3', v3);
const shareUrl = new URL($page.url);
shareUrl.search = params.toString();
return shareUrl.toString();
}
function toQueryValue(value: unknown): string | null {
if (value === null || value === undefined) {
return null;
}
const stringValue = String(value);
return stringValue.trim() ? stringValue : null;
}
async function copyText(text: string) {
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(text);
@@ -125,6 +133,21 @@
}, 1300);
}
function updateTooltipPosition(event: MouseEvent) {
if (!footerControlsEl) return;
const rect = footerControlsEl.getBoundingClientRect();
const x = event.clientX - rect.left;
tooltipX = Math.max(12, Math.min(rect.width - 12, x));
}
function positionTooltipFromButton(button: HTMLButtonElement) {
if (!footerControlsEl) return;
const controlsRect = footerControlsEl.getBoundingClientRect();
const buttonRect = button.getBoundingClientRect();
const centerX = buttonRect.left - controlsRect.left + buttonRect.width / 2;
tooltipX = Math.max(12, Math.min(controlsRect.width - 12, centerX));
}
async function copyLink() {
if (!browser) return;
const url = buildShareUrl();
@@ -237,17 +260,27 @@
</div>
<div class="calc-footer">
<div class="footer-controls">
<div class="footer-controls" bind:this={footerControlsEl}>
<button type="button" class="clear-btn" on:click={clear} aria-label="Clear calculator inputs">
Clear
</button>
<button
type="button"
class="icon-btn"
on:click={copyLink}
on:mouseenter={() => (showHoverTooltip = true)}
on:click={(event) => {
positionTooltipFromButton(event.currentTarget as HTMLButtonElement);
copyLink();
}}
on:mouseenter={(event) => {
showHoverTooltip = true;
updateTooltipPosition(event);
}}
on:mousemove={updateTooltipPosition}
on:mouseleave={() => (showHoverTooltip = false)}
on:focus={() => (showHoverTooltip = true)}
on:focus={(event) => {
showHoverTooltip = true;
positionTooltipFromButton(event.currentTarget as HTMLButtonElement);
}}
on:blur={() => (showHoverTooltip = false)}
aria-label="Copy calculator link"
>
@@ -263,10 +296,10 @@
</svg>
</button>
{#if showHoverTooltip && !showCopyTooltip}
<span class="copy-tooltip hover">Copy link</span>
<span class="copy-tooltip hover" style={`left: ${tooltipX}px;`}>Copy link</span>
{/if}
{#if showCopyTooltip && copyStatus === 'copied'}
<span class="copy-tooltip" class:fading={isTooltipFading}>Link copied!</span>
<span class="copy-tooltip" class:fading={isTooltipFading} style={`left: ${tooltipX}px;`}>Link copied!</span>
{/if}
<span class="sr-only" aria-live="polite">
{copyStatusMessage}
@@ -465,8 +498,7 @@
}
.copy-tooltip {
position: absolute;
top: calc(100% + 0.4rem);
right: 0;
bottom: calc(100% + 0.4rem);
background: color-mix(in srgb, var(--accent) 90%, black 10%);
color: #fff;
border-radius: 6px;
@@ -476,7 +508,7 @@
letter-spacing: 0.02em;
pointer-events: none;
opacity: 1;
transform: translateY(0);
transform: translate(-50%, 0);
transition: opacity 0.35s ease, transform 0.35s ease;
white-space: nowrap;
z-index: 2;
@@ -488,7 +520,7 @@
}
.copy-tooltip.fading {
opacity: 0;
transform: translateY(-0.2rem);
transform: translate(-50%, -0.2rem);
}
.sr-only {
position: absolute;