Carousel 内容轮播

用于内容轮播场景的 MoriUI 组件。

导入

import { Carousel, CarouselAutoplay, CarouselContent, CarouselIndicator, CarouselIndicators, CarouselItem, CarouselNext, CarouselPrevious } from 'moriui'

示例

概览

图片卡片的横向轮播。

<script setup lang="ts">
  import {
    Card,
    CardContent,
    Carousel,
    CarouselContent,
    CarouselItem,
    CarouselNext,
    CarouselPrevious
  } from 'moriui'
</script>

<template>
  <Carousel class="w-full max-w-[12rem] sm:max-w-xs">
    <CarouselContent>
      <CarouselItem v-for="index in 5" :key="index">
        <div class="p-1">
          <Card>
            <CardContent class="flex aspect-square items-center justify-center p-6">
              <span class="text-4xl font-semibold">{{ index }}</span>
            </CardContent>
          </Card>
        </div>
      </CarouselItem>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>

尺寸

不同尺寸的轮播项目。

每项 50% 宽度

每项 33% 宽度

<script setup lang="ts">
  import {
    Card,
    CardContent,
    Carousel,
    CarouselContent,
    CarouselItem,
    CarouselNext,
    CarouselPrevious
  } from 'moriui'
</script>

<template>
  <div class="flex w-full max-w-lg flex-col gap-8">
    <div>
      <h3 class="mb-3 text-sm font-medium text-muted-foreground">
        每项 50% 宽度
      </h3>
      <Carousel :opts="{ align: 'start' }">
        <CarouselContent>
          <CarouselItem v-for="index in 6" :key="index" class="basis-1/2">
            <div class="p-1">
              <Card>
                <CardContent class="flex aspect-square items-center justify-center p-6">
                  <span class="text-3xl font-semibold">{{ index }}</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        </CarouselContent>
        <CarouselPrevious />
        <CarouselNext />
      </Carousel>
    </div>
    <div>
      <h3 class="mb-3 text-sm font-medium text-muted-foreground">
        每项 33% 宽度
      </h3>
      <Carousel :opts="{ align: 'start' }">
        <CarouselContent>
          <CarouselItem v-for="index in 6" :key="index" class="basis-1/3">
            <div class="p-1">
              <Card>
                <CardContent class="flex aspect-square items-center justify-center p-6">
                  <span class="text-3xl font-semibold">{{ index }}</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        </CarouselContent>
        <CarouselPrevious />
        <CarouselNext />
      </Carousel>
    </div>
  </div>
</template>

方向

垂直方向的轮播。

<script setup lang="ts">
  import {
    Card,
    CardContent,
    Carousel,
    CarouselContent,
    CarouselItem,
    CarouselNext,
    CarouselPrevious
  } from 'moriui'
</script>

<template>
  <Carousel orientation="vertical" class="w-full max-w-[12rem] h-60">
    <CarouselContent>
      <CarouselItem v-for="index in 5" :key="index" class="basis-1/2">
        <div class="p-1">
          <Card>
            <CardContent class="flex items-center justify-center p-6">
              <span class="text-3xl font-semibold">{{ index }}</span>
            </CardContent>
          </Card>
        </div>
      </CarouselItem>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>

多项目

同时显示多个项目。

<script setup lang="ts">
  import {
    Card,
    CardContent,
    Carousel,
    CarouselContent,
    CarouselItem,
    CarouselNext,
    CarouselPrevious
  } from 'moriui'
</script>

<template>
  <Carousel class="w-full max-w-lg" :opts="{ align: 'start', slidesToScroll: 2 }">
    <CarouselContent>
      <CarouselItem v-for="index in 6" :key="index" class="basis-1/2">
        <div class="p-1">
          <Card>
            <CardContent class="flex aspect-square items-center justify-center p-6">
              <span class="text-3xl font-semibold">{{ index }}</span>
            </CardContent>
          </Card>
        </div>
      </CarouselItem>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>

间距

自定义项目间距。

<script setup lang="ts">
  import {
    Card,
    CardContent,
    Carousel,
    CarouselContent,
    CarouselItem,
    CarouselNext,
    CarouselPrevious
  } from 'moriui'
</script>

<template>
  <Carousel class="w-full max-w-xs" style="--carousel-gap: 2rem">
    <CarouselContent>
      <CarouselItem v-for="index in 5" :key="index">
        <div class="p-1">
          <Card>
            <CardContent class="flex aspect-square items-center justify-center p-6">
              <span class="text-4xl font-semibold">{{ index }}</span>
            </CardContent>
          </Card>
        </div>
      </CarouselItem>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>

自动播放

CarouselAutoplay 插件。

<script setup lang="ts">
  import {
    Card,
    CardContent,
    Carousel,
    CarouselAutoplay,
    CarouselContent,
    CarouselItem
  } from 'moriui'
</script>

<template>
  <Carousel class="w-full max-w-xs" autoplay>
    <CarouselContent>
      <CarouselItem v-for="index in 5" :key="index">
        <div class="p-1">
          <Card>
            <CardContent class="flex aspect-square items-center justify-center p-6">
              <span class="text-4xl font-semibold">{{ index }}</span>
            </CardContent>
          </Card>
        </div>
      </CarouselItem>
    </CarouselContent>
    <CarouselAutoplay />
  </Carousel>
</template>

RTL

从右到左的轮播方向。

<script setup lang="ts">
  import {
    Card,
    CardContent,
    Carousel,
    CarouselContent,
    CarouselItem,
    CarouselNext,
    CarouselPrevious,
    DirectionProvider
  } from 'moriui'

  const items = ['الأول', 'الثاني', 'الثالث', 'الرابع', 'الخامس']
</script>

<template>
  <DirectionProvider dir="rtl">
    <Carousel class="w-full max-w-xs" :opts="{ direction: 'rtl' }">
      <CarouselContent>
        <CarouselItem v-for="(item, index) in items" :key="index">
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-2xl font-semibold">{{ item }}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  </DirectionProvider>
</template>

使用说明

组合方式

Carousel 由 Content、Item、Previous、Next、Indicators 和 Autoplay 组成,支持多种布局配置。

方向

orientation 支持 horizontal 与 vertical。

间距

通过 class 中的 gap 控制项目间距。

插件

CarouselAutoplay 插件可开启自动轮播。

RTL

方向由 DirectionProvider 控制。

变体

Carousel 的 orientation 支持 horizontal/vertical;opts 支持 slidesToShow、loop、align 等 Embla 选项。

可访问性

Carousel 使用 Embla 的区域和 ARIA 属性。Previous/Next 按钮应提供 aria-label。当前状态可通过 Indicators 展示。

API 参考

属性类型默认值说明
Carousel orientation'horizontal' | 'vertical''horizontal'轮播滚动方向。
Carousel optsCarouselOptions{ loop: false }Embla Carousel 配置项。
Carousel pluginsCarouselPlugin[][]Embla 插件数组。
CarouselContent classHTMLAttributes["class"]undefined合并到内容容器的调用方类。
CarouselItem classHTMLAttributes["class"]undefined合并到每个项目的调用方类。
CarouselPrevious classHTMLAttributes["class"]undefined合并到上一页按钮的调用方类。
CarouselNext classHTMLAttributes["class"]undefined合并到下一页按钮的调用方类。
useCarousel()CarouselApi获取轮播 API 实例进行受控操作。