Files

102 lines
4.0 KiB
Vue

<script setup lang="ts">
import { AnimatePresence, motion, useMotionValue, useSpring } from "motion-v";
import VuesaxIcon from "~/components/ui/VuesaxIcon.vue";
import SectionHead from "~/components/ui/SectionHead.vue";
const industries = computed(() => useSiteStore().sections.industries);
const INDUSTRIES = computed(() => industries.value.items);
const hovered = ref<number | null>(null);
const x = useMotionValue(0);
const y = useMotionValue(0);
const sx = useSpring(x, { stiffness: 220, damping: 26, mass: 0.6 });
const sy = useSpring(y, { stiffness: 220, damping: 26, mass: 0.6 });
const onMove = (e: MouseEvent) => {
x.set(e.clientX);
y.set(e.clientY);
};
</script>
<template>
<section
id="industries"
aria-labelledby="industries-title"
class="relative border-t border-line py-24 md:py-32"
@mousemove="onMove"
>
<div class="mx-auto max-w-[1480px] px-5 md:px-8">
<SectionHead heading-id="industries-title" v-bind="industries.head" />
<div class="mt-16" @mouseleave="hovered = null">
<motion.div
v-for="(ind, i) in INDUSTRIES"
:key="ind.name"
v-bind="fade(i * 0.05)"
data-hover
:class="`group relative flex cursor-pointer items-center justify-between gap-4 border-t border-line px-2 py-7 transition-colors duration-300 hover:bg-panel/40 md:px-4 md:py-9 ${
i === INDUSTRIES.length - 1 ? 'border-b' : ''
}`"
@mouseenter="hovered = i"
>
<div class="flex min-w-0 items-baseline gap-5 md:gap-8">
<span class="shrink-0 font-mono text-xs text-muted">
{{ faNum(String(i + 1).padStart(2, "0")) }}
</span>
<h3
class="truncate text-2xl font-black transition-all duration-300 group-hover:-translate-x-2 group-hover:text-accent md:text-5xl"
>
{{ ind.name }}
</h3>
<span
class="hidden shrink-0 font-mono text-[10px] tracking-[0.3em] text-muted/60 md:inline"
>
{{ ind.nameEn }}
</span>
</div>
<div class="flex shrink-0 items-center gap-4 md:gap-8">
<span v-if="ind.count" class="text-xs text-muted md:text-sm">{{ ind.count }} پروژه</span>
<span
class="flex size-10 items-center justify-center rounded-full border border-line text-muted transition-all duration-300 group-hover:-translate-x-1.5 group-hover:border-accent group-hover:text-accent md:size-12"
>
<VuesaxIcon name="arrow-left" class="size-4 md:size-5" />
</span>
</div>
</motion.div>
</div>
</div>
<!-- ---- floating preview (desktop) ---- -->
<motion.div
:style="{ x: sx, y: sy }"
class="pointer-events-none fixed left-0 top-0 z-40 hidden lg:block"
>
<AnimatePresence>
<motion.div
v-if="hovered !== null"
:key="hovered"
:initial="{ opacity: 0, scale: 0.82, rotate: -3 }"
:animate="{ opacity: 1, scale: 1, rotate: 0 }"
:exit="{ opacity: 0, scale: 0.9, rotate: 2 }"
:transition="{ duration: 0.35, ease: EASE }"
class="relative -ml-40 -mt-28 h-56 w-80 overflow-hidden rounded-xl border border-accent/40 shadow-[0_25px_80px_rgba(0,0,0,0.6)]"
>
<img
:src="INDUSTRIES[hovered]!.image.url"
:alt="INDUSTRIES[hovered]!.image.alt || INDUSTRIES[hovered]!.name"
decoding="async"
class="absolute inset-0 size-full object-cover grayscale-[35%] transition-all duration-500"
/>
<div class="absolute inset-0 bg-accent/15 mix-blend-multiply" />
<div class="absolute inset-0 bg-gradient-to-t from-bg/70 to-transparent" />
<div
class="absolute bottom-3 start-3 rounded-md border border-line bg-bg/80 px-3 py-1.5 font-mono text-[10px] tracking-widest text-ink backdrop-blur"
>
{{ INDUSTRIES[hovered]!.nameEn }}
</div>
</motion.div>
</AnimatePresence>
</motion.div>
</section>
</template>