Skip to content

feat(VInfiniteCarousel): add new component - #23116

Draft
J-Sek wants to merge 1 commit into
devfrom
feat/v-infinite-carousel
Draft

feat(VInfiniteCarousel): add new component#23116
J-Sek wants to merge 1 commit into
devfrom
feat/v-infinite-carousel

Conversation

@J-Sek

@J-Sek J-Sek commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Carousel that loops over

  • suitable as marquee, for logos and decoration
  • supports dragging, arrows, direction, gap, separators, keyboard navigation within, etc.
  • immune to scrolling issues (wheel and focus) thanks to overflow: clip

The behavior will be hard to pull in regular carousel - will bloat that simple variant. Better to ship a separate one.

TODO:

  • support/verify RTL
  • some Sass variables

Quick demo:

<template>
  <v-app :theme="light ? 'light' : 'dark'">
    <v-app-bar title="VInfiniteCarousel">
      <v-switch v-model="light" class="mr-4" label="light theme" hide-details />
      <v-switch v-model="pause" class="mr-4" label="pause" hide-details />
      <v-switch v-model="reverse" class="mr-4" label="reverse" hide-details />
      <v-select
        v-model="showArrows"
        :items="[false, true, 'hover']"
        class="mr-4"
        label="show-arrows"
        max-width="140"
        hide-details
      />
      <v-select
        v-model="maskSize"
        :items="[0, 40, 80]"
        class="mr-4"
        label="mask"
        max-width="140"
        hide-details
      />
      <v-select
        v-model="shiftDistance"
        :items="['100%', '50%', 200, '10rem']"
        class="mr-4"
        label="shift-distance"
        max-width="140"
        hide-details
      />
    </v-app-bar>

    <v-main>
      <v-container>
        <v-sheet class="mb-12" rounded>
          <v-infinite-carousel
            :auto-play="autoPlay"
            :mask="mask"
            :shift-distance="shiftDistance"
            :show-arrows="showArrows"
            class="py-4"
            gap="1rem"
            draggable
          >
            <v-chip v-for="item in items" :key="item" color="primary">
              {{ item }}
            </v-chip>
          </v-infinite-carousel>
        </v-sheet>

        <div class="d-flex ga-8 mb-12">
          <v-sheet height="300" width="220" rounded>
            <v-infinite-carousel
              :auto-play="autoPlay"
              :mask="mask"
              :shift-distance="shiftDistance"
              :show-arrows="showArrows"
              direction="vertical"
              draggable
            >
              <v-chip v-for="item in items" :key="item" color="primary" block>
                {{ item }}
              </v-chip>
            </v-infinite-carousel>
          </v-sheet>

          <v-sheet class="align-self-start flex-grow-1" rounded>
            <v-infinite-carousel
              :auto-play="autoPlay"
              :mask="mask"
              :shift-distance="shiftDistance"
              :show-arrows="showArrows"
              class="py-4"
              draggable
            >
              <v-chip color="info" label>only</v-chip>
              <v-chip color="warning" label>three</v-chip>
              <v-chip color="success" label>chips</v-chip>
            </v-infinite-carousel>
          </v-sheet>
        </div>

        <v-infinite-carousel
          :auto-play="autoPlay"
          :mask="mask"
          :shift-distance="shiftDistance"
          :show-arrows="showArrows"
          gap="2.5rem"
          style="user-select: none"
        >
          <template #separator>
            <v-icon color="primary" icon="mdi-circle-small" />
          </template>

          <span
            v-for="item in items"
            :key="item"
            class="text-headline-small text-uppercase font-weight-bold font-italic opacity-50"
          >{{ item }}</span>
        </v-infinite-carousel>
      </v-container>
    </v-main>
  </v-app>
</template>

<script setup lang="ts">
  import { computed, ref } from 'vue'

  const light = ref(false)
  const pause = ref(false)
  const reverse = ref(false)
  const showArrows = ref<boolean | 'hover'>('hover')
  const maskSize = ref(40)
  const shiftDistance = ref<string | number>('50%')

  const autoPlay = computed(() => !pause.value && { speed: 35, reverse: reverse.value })
  const mask = computed(() => maskSize.value > 0 && { size: maskSize.value })
  const items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`)
</script>

@J-Sek J-Sek self-assigned this Aug 13, 2026
@J-Sek J-Sek added the C: New Component This issue would need a new component to be developed. label Aug 13, 2026
@J-Sek J-Sek added this to the v4.x.x milestone Aug 13, 2026
@J-Sek
J-Sek force-pushed the feat/v-infinite-carousel branch from de024cc to 95a581b Compare August 19, 2026 11:15
@J-Sek
J-Sek force-pushed the feat/v-infinite-carousel branch from 95a581b to 77ae141 Compare August 19, 2026 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C: New Component This issue would need a new component to be developed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant