77 lines
2.6 KiB
Vue
77 lines
2.6 KiB
Vue
<script setup lang="ts">
|
|
import { AnimatePresence, motion } from "motion-v";
|
|
import VuesaxIcon from "~/components/ui/VuesaxIcon.vue";
|
|
import SectionHead from "~/components/ui/SectionHead.vue";
|
|
|
|
const testimonials = computed(() => useSiteStore().sections.testimonials);
|
|
const QUOTES = computed(() => testimonials.value.items);
|
|
|
|
const idx = ref(0);
|
|
const q = computed(() => QUOTES.value[idx.value]);
|
|
let t: ReturnType<typeof setInterval> | undefined;
|
|
|
|
onMounted(() => {
|
|
t = setInterval(() => (idx.value = (idx.value + 1) % Math.max(1, QUOTES.value.length)), 7000);
|
|
});
|
|
onBeforeUnmount(() => clearInterval(t));
|
|
</script>
|
|
|
|
<template>
|
|
<section
|
|
v-if="QUOTES.length"
|
|
aria-labelledby="testimonials-title"
|
|
class="relative overflow-hidden border-t border-line py-24 md:py-32"
|
|
>
|
|
<div class="absolute inset-0 bg-grid opacity-40" />
|
|
<div
|
|
class="pointer-events-none absolute -top-10 -end-10 select-none font-mono text-[18vw] font-bold leading-none text-outline opacity-50"
|
|
>
|
|
"
|
|
</div>
|
|
|
|
<div class="relative mx-auto max-w-4xl px-5 text-center md:px-8">
|
|
<SectionHead heading-id="testimonials-title" center v-bind="testimonials.head" />
|
|
|
|
<div class="mt-14 flex min-h-[320px] flex-col items-center md:min-h-[280px]">
|
|
<span
|
|
class="flex size-16 items-center justify-center rounded-full border border-accent/30 bg-accent/10"
|
|
>
|
|
<VuesaxIcon name="quote-up" class="size-7 text-accent" />
|
|
</span>
|
|
|
|
<AnimatePresence mode="wait">
|
|
<motion.blockquote
|
|
v-if="q"
|
|
:key="idx"
|
|
:initial="{ opacity: 0, y: 26 }"
|
|
:animate="{ opacity: 1, y: 0 }"
|
|
:exit="{ opacity: 0, y: -26 }"
|
|
:transition="{ duration: 0.55, ease: EASE }"
|
|
class="mt-8"
|
|
>
|
|
<p class="text-xl font-bold leading-[2.1] text-ink/90 md:text-2xl md:leading-[2]">
|
|
«{{ q.text }}»
|
|
</p>
|
|
<footer class="mt-8">
|
|
<div class="text-lg font-black">{{ q.name }}</div>
|
|
<div class="mt-2 font-mono text-xs text-muted">{{ q.role }}</div>
|
|
</footer>
|
|
</motion.blockquote>
|
|
</AnimatePresence>
|
|
</div>
|
|
|
|
<div class="mt-12 flex items-center justify-center gap-3">
|
|
<button
|
|
v-for="(_, i) in QUOTES"
|
|
:key="i"
|
|
:aria-label="`نظر شماره ${faNum(i + 1)}`"
|
|
:class="`h-1.5 rounded-full transition-all duration-500 ${
|
|
i === idx ? 'w-12 bg-accent' : 'w-4 bg-line hover:bg-muted'
|
|
}`"
|
|
@click="idx = i"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|