refactor: media cards use proper <a href> links instead of JS navigation

MediaCard, MediaRow, CollageHero, HeroSection, and MediaDetail cast
cards now render as <a> tags with real hrefs. Modified clicks
(ctrl+click, middle-click) navigate natively, enabling open-in-new-tab
and link copying. Plain left-clicks continue through the existing
showDetail flow for side-effects like focus-state saving.
This commit is contained in:
2026-05-25 14:21:13 +00:00
parent 1d3d682b60
commit 76c426546b
9 changed files with 104 additions and 29 deletions
+24 -4
View File
@@ -1,9 +1,11 @@
<template>
<div
<component
:is="href ? 'a' : 'div'"
class="media-card"
v-bind="navAttributes"
:data-item-id="item.id"
@click="$emit('click')"
:href="href || undefined"
@click="handleClick"
@keydown.enter.prevent="$emit('click')"
>
<div class="media-card-poster">
@@ -78,7 +80,7 @@
</div>
</template>
</div>
</div>
</component>
</template>
<script setup lang="ts">
@@ -91,12 +93,30 @@ const props = defineProps<{
item: MediaItem
navRow?: number
navCol?: number
href?: string
}>()
defineEmits<{
const emit = defineEmits<{
click: []
}>()
function handleClick(event: MouseEvent) {
// Let modified clicks (middle-click, ctrl+click, etc.) navigate natively
if (
event.button !== 0 ||
event.ctrlKey ||
event.metaKey ||
event.shiftKey ||
event.altKey
) {
return
}
// Prevent default navigation for plain left-clicks and synthetic clicks
// so that parent handlers can manage side-effects and routing
event.preventDefault()
emit("click")
}
const navAttributes = computed(() => {
if (props.navRow !== undefined && props.navCol !== undefined) {
return navAttrs(props.navRow, props.navCol)