Files
anyame-frontend-vue/app/components/ui/internal/MediaImageCard.vue

101 lines
3.6 KiB
Vue

<script setup lang="ts">
import tinycolor from "tinycolor2";
import type { VNodeRef } from "vue";
import Badge from "../badge/Badge.vue";
import { Dot } from "lucide-vue-next";
const imageElement = shallowRef<VNodeRef | null>(null);
const palette = useVibrantPalette(imageElement);
const paletteVibrantHsl = ref<string>('');
watch(palette, () => {
if (!palette.value?.Vibrant) return;
const [hue, saturation, lightness] = palette.value.Vibrant.hsl;
const lighterColor = tinycolor({ h: hue * 360, s: saturation, l: lightness }).brighten().desaturate().toHslString()
paletteVibrantHsl.value = lighterColor;
});
interface Props {
id: number;
image_url: string;
image_alt?: string;
title: string;
type: string;
subtitle?: string;
description?: string;
tooltipEnabled?: boolean;
tooltipMetadata?: {
studio: string;
type: string;
episodes: number;
rating: number;
tags?: string[];
};
tooltipCollisionBoundary?: Element;
dynamicColor?: boolean;
onClick?: () => void;
onHover?: (isHovering: boolean) => void;
}
const props = defineProps<Props>();
</script>
<template>
<NuxtLink :to="`anime/${id}`">
<div class="h-full overflow-hidden max-w-64">
<div class="flex flex-col gap-2 cursor-pointer text-muted-foreground vibrant-color">
<TooltipProvider>
<Tooltip>
<TooltipTrigger as-child>
<div>
<NuxtImg class="rounded-lg" ref="imageElement" :src="props.image_url"
sizes="128px md:256px" quality="100" />
<p class="text-lg line-clamp-2 font-semibold max-w-[12ch] 2xl:max-w-full">
{{ props.title }}
</p>
</div>
</TooltipTrigger>
<TooltipContent :sideOffset="16" :collisionBoundary="props.tooltipCollisionBoundary"
:avoidCollisions="true" side="right" tooltipColor="muted" tooltipArrowColor="muted">
<div class="flex flex-col gap-1 m-4">
<div class="flex">
<p class="text-xl font-bold truncate max-w-[24ch]">{{ props.title }}</p>
</div>
<p class="text-lg font-semibold tracking-wider" :style="{ color: paletteVibrantHsl }">{{
props.tooltipMetadata?.studio }}
</p>
<div class="flex items-center text-base font-semibold">
<p>{{ props.tooltipMetadata?.type }}</p>
<Dot />
<p>{{ props.tooltipMetadata?.rating }} episodes</p>
</div>
<div class="flex gap-2">
<Badge v-for="tag in props.tooltipMetadata?.tags">
{{ tag }}
</Badge>
</div>
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</div>
</NuxtLink>
</template>
<style scoped>
.vibrant-color:hover {
color: v-bind(paletteVibrantHsl);
}
.vibrant-color {
transition: color ease-in 0.1s;
}
</style>