82 lines
2.9 KiB
Vue
82 lines
2.9 KiB
Vue
<template>
|
|
<article
|
|
class="group relative flex h-full flex-col overflow-hidden rounded-2xl border border-[var(--color-border)]/40 bg-[var(--card)]/95 shadow-sm transition-transform duration-300 hover:-translate-y-0.5 hover:shadow-xl"
|
|
>
|
|
<!-- Header / image -->
|
|
<div class="flex items-start gap-4 p-4 sm:p-5">
|
|
<div class="relative shrink-0">
|
|
<div
|
|
class="h-40 w-28 rounded-xl bg-cover bg-center bg-no-repeat shadow-md ring-1 ring-[var(--color-border)]/50"
|
|
:style="{
|
|
backgroundImage: `url(${resolvedImageUrl})`,
|
|
transform: orientation === 'reversed' ? 'rotate(180deg)' : 'none'
|
|
}"
|
|
></div>
|
|
<div
|
|
class="absolute -bottom-2 -left-2 flex h-8 w-8 items-center justify-center rounded-full border-2 border-[var(--color-border)]/60 bg-[var(--secondary)] text-xs font-black text-[var(--foreground)] shadow"
|
|
:title="`Carte #${cardNumber}`"
|
|
>
|
|
{{ cardNumber }}
|
|
</div>
|
|
<div
|
|
v-if="orientation"
|
|
class="absolute top-2 right-2 rounded-full px-2 py-0.5 text-[10px] font-bold tracking-wide text-white shadow"
|
|
:class="orientation === 'reversed' ? 'bg-red-600/90' : 'bg-[var(--primary)]'"
|
|
>
|
|
{{ orientation === 'reversed' ? 'Inversée' : 'Droite' }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="min-w-0 flex-1">
|
|
<h3 class="font-title text-lg font-black leading-snug text-[var(--foreground)]">
|
|
{{ name }}
|
|
</h3>
|
|
<p class="mt-1 text-xs uppercase tracking-wider text-[var(--muted-foreground)]">
|
|
Carte #{{ cardNumber }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Description -->
|
|
<div class="relative px-4 pb-4 sm:px-5 sm:pb-5">
|
|
<div :class="[ collapsed ? 'max-h-40 overflow-hidden' : 'max-h-none', 'text-sm leading-relaxed text-[var(--foreground)]/85']">
|
|
<div v-html="description"></div>
|
|
</div>
|
|
|
|
<!-- Fade overlay when collapsed -->
|
|
<div
|
|
v-if="collapsed"
|
|
class="pointer-events-none absolute inset-x-0 bottom-12 h-16 bg-gradient-to-t from-[var(--card)] to-transparent"
|
|
></div>
|
|
|
|
<div class="mt-3 flex justify-end">
|
|
<button
|
|
type="button"
|
|
@click="collapsed = !collapsed"
|
|
class="rounded-full border border-[var(--color-border)]/60 bg-[var(--secondary)]/60 px-3 py-1 text-xs font-semibold text-[var(--foreground)] transition-colors hover:bg-[var(--secondary)]"
|
|
>
|
|
{{ collapsed ? 'Lire plus' : 'Réduire' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, ref } from 'vue'
|
|
|
|
interface Props {
|
|
cardNumber: number
|
|
name: string
|
|
imageUrl?: string
|
|
orientation?: string
|
|
description: string
|
|
}
|
|
|
|
const props = defineProps<Props>()
|
|
|
|
const resolvedImageUrl = computed(() => props.imageUrl || `/cards/${props.cardNumber + 1}.png`)
|
|
|
|
const collapsed = ref(true)
|
|
</script>
|