Files
frontend/src/components/TestimonialsSection.vue
T
austnv b89f92953d # feature: add dark/light theme support
Realized by prefers-color-scheme media queries with Tailwind CSS
2026-05-24 02:00:54 +03:00

125 lines
4.4 KiB
Vue

<template>
<section id="testimonials" class="px-6 py-20 md:px-12 max-w-7xl mx-auto">
<h2 class="text-3xl md:text-4xl font-bold text-center mb-14">
Отзывы пользователей
</h2>
<div class="relative group">
<Swiper
:modules="[Navigation, Pagination, Mousewheel]"
:slides-per-view="1"
:space-between="16"
:loop="true"
:mousewheel="{ forceToAxis: true, sensitivity: 1 }"
:navigation="{
prevEl: swiperPrev,
nextEl: swiperNext,
}"
:pagination="{
clickable: true,
el: swiperPagination,
bulletClass: 'swiper-bullet',
bulletActiveClass: 'swiper-bullet-active'
}"
:breakpoints="{
640: { slidesPerView: 2 },
1024: { slidesPerView: 3 }
}"
:grab-cursor="true"
:speed="600"
class="pb-10!"
@swiper="onSwiper"
>
<SwiperSlide v-for="(review, i) in reviews" :key="i">
<div class="bg-white dark:bg-gray-900 rounded-2xl p-6 border border-gray-200 dark:border-gray-800 aspect-4/5 flex flex-col h-full">
<div class="flex items-center gap-4 mb-4">
<img :src="review.avatar" class="w-12 h-12 rounded-full" alt="avatar" />
<div>
<p class="font-semibold">{{ review.name }}</p>
<p class="text-sm text-gray-500 dark:text-gray-400">{{ review.username }}</p>
</div>
</div>
<p class="text-gray-500 dark:text-gray-400 italic flex-1">{{ review.text }}</p>
</div>
</SwiperSlide>
</Swiper>
<button
ref="swiperPrev"
class="absolute left-0 top-1/2 -translate-y-1/2 bg-gray-200 hover:bg-gray-300/80 dark:bg-gray-800/80 dark:hover:bg-gray-700 text-gray-900 dark:text-white p-2 rounded-full shadow-lg backdrop-blur opacity-0 group-hover:opacity-100 transition-opacity ml-2 z-10"
>
<ChevronLeft class="w-5 h-5" />
</button>
<button
ref="swiperNext"
class="absolute right-0 top-1/2 -translate-y-1/2 bg-gray-200 hover:bg-gray-300/80 dark:bg-gray-800/80 dark:hover:bg-gray-700 text-gray-900 dark:text-white p-2 rounded-full shadow-lg backdrop-blur opacity-0 group-hover:opacity-100 transition-opacity mr-2 z-10"
>
<ChevronRight class="w-5 h-5" />
</button>
</div>
<div ref="swiperPagination" class="flex justify-center mt-6 gap-2"></div>
</section>
</template>
<script setup>
import { ref } from 'vue'
import { ChevronLeft, ChevronRight } from '@lucide/vue'
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Navigation, Pagination, Mousewheel } from 'swiper/modules'
import 'swiper/css'
import 'swiper/css/navigation'
import 'swiper/css/pagination'
const swiperPrev = ref(null)
const swiperNext = ref(null)
const swiperPagination = ref(null)
const reviews = [
{
avatar: '/images/alex.jpg',
name: 'Алексей',
username: '@austnv',
text: 'Скорость просто отличная, все сайты открываются мгновенно. Очень доволен сервисом!'
},
{
avatar: '/images/max.jpg',
name: 'Макс',
username: '@max_pelegrino',
text: 'Пользуюсь уже полгода — ни разу не подвел. Удобное приложение, все интуитивно понятно.'
},
{
avatar: '/images/dani.jpg',
name: 'Дани',
username: '@dani_sultan',
text: 'Лучшее решение для обхода блокировок. Подключаюсь к зарубежным серверам за секунды.'
},
{
avatar: '/images/nikita.jpg',
name: 'Никита',
username: '@nikita_novikov',
text: 'Очень простой интерфейс, даже мои родители разобрались. Спасибо!'
}
]
// Функция вызывается после инициализации Swiper
const onSwiper = (swiper) => {
// Опционально: можно управлять экземпляром Swiper
}
</script>
<style scoped>
:deep(.swiper-bullet) {
width: 0.75rem;
height: 0.75rem;
border-radius: 9999px;
background-color: #4b5563;
display: inline-block;
margin: 0 0.25rem;
cursor: pointer;
transition: background-color 0.2s;
}
:deep(.swiper-bullet-active) {
background-color: #2563eb;
}
</style>