@wikicasa-dev/components · Media · primitive

SwiperThumbnailPrimitive

Thumbnail strip linked to a SwiperRootPrimitive carousel; tapping a thumbnail shows that slide.

Thumbnail strip linked to a SwiperRootPrimitive carousel; tapping a thumbnail shows that slide.

import SwiperThumbnailPrimitive from "@wikicasa-dev/components/generic/carousel/Primitive/SwiperThumbnailPrimitive";

A second, smaller Swiper that acts as the carousel's thumbnail rail: tapping a thumbnail moves the main carousel there, and the current one gets .swiper-slide-thumb-active. Put it in SwiperRootPrimitive's #thumbs slot (outside the clipped carousel box) and fill it with SwiperSlideImagePrimitive slides using lazy, so only the thumbnails on screen (plus preload-count, default 1, on each side) load. See SwiperRootPrimitive for the full composition.

swiper-options takes Swiper options for the strip itself (e.g. slidesPerView, spaceBetween, freeMode: true for free scrolling); root-classes and wrapper-classes add classes to its .swiper and .swiper-wrapper elements.

Usage

<script setup lang="ts">
import SwiperRootPrimitive from "@wikicasa-dev/components/generic/carousel/Primitive/SwiperRootPrimitive";
import SwiperPrimitive from "@wikicasa-dev/components/generic/carousel/Primitive/SwiperPrimitive";
import SwiperSlideImagePrimitive from "@wikicasa-dev/components/generic/carousel/Primitive/SwiperSlideImagePrimitive";
import SwiperThumbnailPrimitive from "@wikicasa-dev/components/generic/carousel/Primitive/SwiperThumbnailPrimitive";

const photos = ["/img/rustico-1.jpg", "/img/rustico-2.jpg", "/img/rustico-3.jpg", "/img/rustico-4.jpg", "/img/rustico-5.jpg"];
</script>

<template>
  <SwiperRootPrimitive class="gallery">
    <SwiperPrimitive>
      <SwiperSlideImagePrimitive v-for="(src, i) in photos" :key="src" :src="src" :alt="`Rustico in Umbria, foto ${i + 1}`" :lazy="i > 0" />
    </SwiperPrimitive>
    <template #thumbs>
      <SwiperThumbnailPrimitive :swiper-options="{ slidesPerView: 4, spaceBetween: 8, freeMode: true }">
        <SwiperSlideImagePrimitive v-for="(src, i) in photos" :key="src" :src="src" :alt="`Miniatura ${i + 1}`" lazy img-classes="thumb" />
      </SwiperThumbnailPrimitive>
    </template>
  </SwiperRootPrimitive>
</template>

<style scoped>
.gallery :deep(.thumb) { width: 80px; height: 80px; object-fit: cover; border-radius: 8px; opacity: 0.6; }
.gallery :deep(.swiper-slide-thumb-active .thumb) { opacity: 1; }
</style>

Do / Don't

  • Do place it in the root's #thumbs slot, rendered from the start (it registers with the root while the carousel is created).
  • Do use thumbnail-sized image URLs, not the full photos.
  • Don't pass thumbs, watchSlidesProgress or slideToClickedSlide in swiper-options; the link to the carousel sets them.
  • The strip's Swiper instance is exposed as swiper and passed by @init.

API

Generated from the component's types. Do not edit by hand.

Props

Name Type Default Required Description
dataCy string
rootClasses ClassTypeProp
wrapperClasses ClassTypeProp
swiperOptions SwiperThumbnailPrimitiveProps
preloadCount number 1 Thumbnails to promote beyond each edge of the visible window. A rail whose next thumbnail pops in under the finger reads as broken, so this leans one slide out by default. Deliberately not Swiper's lazyPreloadPrevNext: that option drives Swiper's own loading="lazy" preloading, which these slides do not use - borrowing it would both misname the knob and switch on a second preloading pass on every slide change.

Events

Name Payload
init [Swiper]

v-model

None.

Slots

Name Slot props
default

Exposed (template ref)

Name Type
swiper Nullable<Swiper>