feat: card highlight system for cross-entity navigation

When clicking a CrossLink, the target entity ID is passed as
?highlight=<id> in the URL. The destination page:
1. Shows a semi-transparent dim overlay (z-index: 10)
2. Finds the card with data-entity-id matching the ID
3. Scrolls to it smoothly (block: center)
4. Applies a pulsing primary-color box-shadow animation (z-index: 11)
5. Cleans up overlay + animation after 2 seconds

If the card isn't in DOM yet (data still loading), a MutationObserver
waits up to 5 seconds for it to appear.

Changes:
- New highlight.ts utility with highlightFromUrl(), MutationObserver,
  dim overlay management
- Card component accepts entityId prop → data-entity-id attribute
- CrossLink accepts entityId prop → appends ?highlight=<id> to href
- All 9 entity pages: Card elements have entityId, highlightFromUrl()
  called after data loads
- CSS: cardHighlight keyframe animation + nav-dim-overlay styles
This commit is contained in:
2026-03-21 23:59:25 +03:00
parent 227b9c2e92
commit f0f49db21e
13 changed files with 202 additions and 27 deletions
+10 -2
View File
@@ -6,22 +6,30 @@
href,
icon = 'mdiLink',
label,
entityId = null,
title = '',
}: {
href: string;
icon?: string;
label: string;
entityId?: number | string | null;
title?: string;
} = $props();
const targetHref = $derived(
entityId != null
? `${href.split('?')[0]}?highlight=${entityId}${href.includes('?') ? '&' + href.split('?')[1] : ''}`
: href
);
function navigate(e: MouseEvent) {
e.preventDefault();
e.stopPropagation();
goto(href);
goto(targetHref);
}
</script>
<a {href} class="crosslink" title={title || label} onclick={navigate}>
<a href={targetHref} class="crosslink" title={title || label} onclick={navigate}>
<MdiIcon name={icon} size={12} />
<span>{label}</span>
</a>