carousel
Carousel with dots navigation and content overlays
Carousel with dots navigation and content overlays
Загрузка превью…
src/carousel/c-carousel-11.vue
<script setup lang="ts">
import { ref, watch } from "vue"
import type { EmblaCarouselType } from "embla-carousel"
import { Card } from "@/components/ui/card"
import { Carousel, CarouselContent, CarouselItem } from "@/components/ui/carousel"
import { cn } from "@/lib/utils"
const PIXEL = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="
const slides = [0, 1, 2, 3, 4]
const api = ref<EmblaCarouselType>()
const current = ref(1)
const count = ref(0)
watch(
api,
(emblaApi) => {
if (!emblaApi) return
count.value = emblaApi.scrollSnapList().length
current.value = emblaApi.selectedScrollSnap()
emblaApi.on("select", () => {
current.value = emblaApi.selectedScrollSnap()
})
},
{ immediate: true }
)
</script>
<template>
<Carousel :set-api="(a) => (api = a)" :opts="{ startIndex: 1, duration: 0 }" class="w-full max-w-xs">
<CarouselContent>
<CarouselItem v-for="index in slides" :key="index">
<div class="p-1">
<Card class="group/card relative aspect-square overflow-hidden border-0 p-0">
<img
:src="PIXEL"
:alt="`Slide ${index + 1}`"
width="800"
height="800"
class="absolute inset-0 size-full scale-100 object-cover transition-transform duration-500 ease-in-out group-hover/card:scale-105"
/>
<div class="absolute inset-x-0 bottom-0 h-1/2 bg-linear-to-t from-black/80 to-transparent" />
<div class="absolute inset-0 top-auto flex flex-col justify-end bg-black/20 p-4">
<h3 class="text-xl font-bold text-white">Slide {{ index + 1 }}</h3>
<p class="text-sm text-white/90">Feature description for slide {{ index + 1 }}.</p>
</div>
</Card>
</div>
</CarouselItem>
</CarouselContent>
<div class="flex justify-center gap-2 py-3">
<button
v-for="index in count"
:key="index - 1"
:class="
cn(
'h-2 cursor-pointer rounded-full transition-all duration-500 ease-in-out',
index - 1 === current ? 'bg-primary w-4 opacity-100' : 'bg-muted-foreground w-2 opacity-30 hover:opacity-50'
)
"
:aria-label="`Go to slide ${index}`"
@click="api?.scrollTo(index - 1)"
/>
</div>
</Carousel>
</template>