feat(Carousel): implement component (#2288)

This commit is contained in:
Benjamin Canac
2024-10-08 17:12:43 +02:00
committed by GitHub
parent 69a6e11c52
commit 68ee3f11ca
43 changed files with 1553 additions and 27 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" arrows :items="items" class="w-full max-w-xs mx-auto">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,29 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/320?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/320?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/320?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
auto-height
arrows
dots
:items="items"
:ui="{
container: 'transition-[height]',
controls: 'absolute -top-8 inset-x-12',
dots: '-top-7',
dot: 'w-6 h-1'
}"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,24 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/468/468?random=1',
'https://picsum.photos/468/468?random=2',
'https://picsum.photos/468/468?random=3',
'https://picsum.photos/468/468?random=4',
'https://picsum.photos/468/468?random=5',
'https://picsum.photos/468/468?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
loop
dots
arrows
auto-scroll
:items="items"
:ui="{ item: 'basis-1/3' }"
>
<img :src="item" width="234" height="234" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,24 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/468/468?random=1',
'https://picsum.photos/468/468?random=2',
'https://picsum.photos/468/468?random=3',
'https://picsum.photos/468/468?random=4',
'https://picsum.photos/468/468?random=5',
'https://picsum.photos/468/468?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
loop
arrows
dots
:autoplay="{ delay: 2000 }"
:items="items"
:ui="{ item: 'basis-1/3' }"
>
<img :src="item" width="234" height="234" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,25 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/528/528?random=1',
'https://picsum.photos/528/528?random=2',
'https://picsum.photos/528/528?random=3',
'https://picsum.photos/528/528?random=4',
'https://picsum.photos/528/528?random=5',
'https://picsum.photos/528/528?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
class-names
arrows
:items="items"
:ui="{
item: 'basis-[70%] transition-opacity [&:not(.is-snapped)]:opacity-10'
}"
class="mx-auto max-w-sm"
>
<img :src="item" width="264" height="264" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" dots :items="items" class="w-full max-w-xs mx-auto">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" dots :items="items" :ui="{ item: 'basis-1/3' }">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,23 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
fade
arrows
dots
:items="items"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" class="w-full max-w-xs mx-auto">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/468/468?random=1',
'https://picsum.photos/468/468?random=2',
'https://picsum.photos/468/468?random=3',
'https://picsum.photos/468/468?random=4',
'https://picsum.photos/468/468?random=5',
'https://picsum.photos/468/468?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-1/3' }">
<img :src="item" width="234" height="234" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,22 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
orientation="vertical"
:items="items"
class="w-full max-w-xs mx-auto"
:ui="{ container: 'h-[336px]' }"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,23 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
arrows
:prev="{ color: 'primary' }"
:next="{ variant: 'solid' }"
:items="items"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,28 @@
<script setup lang="ts">
defineProps<{
prevIcon?: string
nextIcon?: string
}>()
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
arrows
:prev-icon="prevIcon"
:next-icon="nextIcon"
:items="items"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -0,0 +1,22 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/468/468?random=1',
'https://picsum.photos/468/468?random=2',
'https://picsum.photos/468/468?random=3',
'https://picsum.photos/468/468?random=4',
'https://picsum.photos/468/468?random=5',
'https://picsum.photos/468/468?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
loop
wheel-gestures
:items="items"
:ui="{ item: 'basis-1/3' }"
>
<img :src="item" width="234" height="234" class="rounded-lg">
</UCarousel>
</template>

View File

@@ -36,7 +36,7 @@ Tailwind CSS v4 takes a CSS-first configuration approach, you now customize your
</style>
```
The `@theme` directive tells Tailwind to make new utilities and variants available based on those variables. It's the equivalent of the `theme.extend` key in Tailwind CSS v3 `tailwind.config.ts` file.
The `@theme` directive tells Tailwind to make new utilities and variants available based on these variables. It's the equivalent of the `theme.extend` key in Tailwind CSS v3 `tailwind.config.ts` file.
::note
You can learn more about this on [https://tailwindcss.com/blog/tailwindcss-v4-alpha](https://tailwindcss.com/blog/tailwindcss-v4-alpha#css-first-configuration).
@@ -383,7 +383,7 @@ export default {
::
::note
::warning
Components without slots don't have a [`ui` prop](#ui-prop), only the [`class` prop](#class-prop) is available to override styles.
::
@@ -434,11 +434,11 @@ The `defaultVariants` property specifies the default values for each variant. It
You have multiple ways to customize the appearance of Nuxt UI components, you can do it for all components at once or on a per-component basis.
::tip
::note
Tailwind Variants uses [tailwind-merge](https://github.com/dcastil/tailwind-merge) under the hood to merge classes so you don't have to worry about conflicting classes.
::
::note
::tip
You can explore the theme for each component in two ways:
- Check the `Theme` section in the documentation of each individual component.
@@ -463,7 +463,9 @@ export default defineAppConfig({
})
```
::note
In this example, the `font-bold` class will override the default `font-medium` class on all buttons.
::
### `ui` prop
@@ -492,7 +494,9 @@ slots:
---
::
::note
In this example, the `trailingIcon` slot is overwritten with `size-3` even though the `md` size variant would apply a `size-5` class to it.
::
### `class` prop
@@ -506,3 +510,7 @@ slots:
default: Button
---
::
::note
In this example, the `font-bold` class will override the default `font-medium` class on this button.
::

View File

@@ -69,7 +69,7 @@ npm install @iconify-json/{collection_name}
For example, to use the `i-uil-github` icon, install it's collection with `@iconify-json/uil`. This way the icons can be served locally or from your serverless functions, which is faster and more reliable on both SSR and client-side.
::tip{to="https://github.com/nuxt/icon?tab=readme-ov-file#iconify-dataset" target="_blank"}
::note{to="https://github.com/nuxt/icon?tab=readme-ov-file#iconify-dataset" target="_blank"}
Read more about this in the `@nuxt/icon` documentation.
::
@@ -109,7 +109,7 @@ Then you can use the icons like this:
</template>
```
::tip{to="https://github.com/nuxt/icon?tab=readme-ov-file#custom-local-collections" target="_blank"}
::note{to="https://github.com/nuxt/icon?tab=readme-ov-file#custom-local-collections" target="_blank"}
Read more about this in the `@nuxt/icon` documentation.
::

View File

@@ -25,6 +25,6 @@ Nuxt UI automatically registers the `@nuxt/fonts` module for you, so there's no
That's it! Nuxt Fonts will detect this and you should immediately see the web font loaded in your browser.
::tip{to="https://fonts.nuxt.com/advanced" target="_blank"}
::note{to="https://fonts.nuxt.com/advanced" target="_blank"}
Read more about how `@nuxt/fonts` work behind the scenes to optimize your fonts.
::

View File

@@ -278,6 +278,7 @@ ignore:
- exactQuery
- exactHash
- external
- onClick
---
::

View File

@@ -123,6 +123,7 @@ ignore:
- exactQuery
- exactHash
- external
- onClick
---
::

View File

@@ -248,6 +248,7 @@ ignore:
- exactHash
- external
- active
- onClick
---
::

View File

@@ -1,34 +1,419 @@
---
description: A carousel with motion and swipe support.
description: A carousel with motion and swipe built using Embla.
links:
- label: Embla
to: https://www.embla-carousel.com/api/
icon: i-custom-embla-carousel
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/Carousel.vue
navigation:
badge:
label: Todo
color: neutral
disabled: true
---
## Usage
## Examples
### Items
<!-- ## API
Use the `items` prop as an array and render each item using the default slot:
::note
Use your mouse to drag the carousel horizontally on desktop.
::
::component-example
---
name: 'carousel-items-example'
class: 'p-8'
---
::
You can control how many items are visible by using the [`basis`](https://tailwindcss.com/docs/flex-basis) / [`width`](https://tailwindcss.com/docs/width) utility classes on the `item`:
::component-example
---
name: 'carousel-items-multiple-example'
class: 'p-8 px-16'
---
::
### Orientation
Use the `orientation` prop to change the orientation of the Progress. Defaults to `horizontal`.
::note
Use your mouse to drag the carousel vertically on desktop.
::
::component-example
---
name: 'carousel-orientation-example'
class: 'p-8'
---
::
::caution
You need to specify a `height` on the container in vertical orientation.
::
### Arrows
Use the `arrows` prop to display prev and next buttons.
::component-example
---
name: 'carousel-arrows-example'
class: 'p-8'
---
::
### Prev / Next
Use the `prev` and `next` props to customize the prev and next buttons.
::component-example
---
name: 'carousel-prev-next-example'
class: 'p-8'
---
::
### Prev Icon / Next Icon
Use the `prev-icon` and `next-icon` props to customize the buttons [Icon](/components/icon). Defaults to `i-heroicons-arrow-left-20-solid` / `i-heroicons-arrow-right-20-solid`.
::component-example
---
name: 'carousel-prev-next-icon-example'
class: 'p-8'
options:
- name: 'prevIcon'
label: 'prevIcon'
default: 'i-heroicons-chevron-left'
- name: 'nextIcon'
label: 'nextIcon'
default: 'i-heroicons-chevron-right'
---
::
::tip{to="/getting-started/icons#theme"}
You can customize these icons globally in your `app.config.ts` under `ui.icons.arrowLeft` / `ui.icons.arrowRight` key.
::
### Dots
Use the `dots` prop to display a list of dots to scroll to a specific slide.
::component-example
---
name: 'carousel-dots-example'
class: 'p-8 pb-12'
---
::
The number of dots is based on the number of slides displayed in the view:
::component-example
---
name: 'carousel-dots-multiple-example'
class: 'p-8 px-16 pb-12'
---
::
## Plugins
The Carousel component implements the official [Embla Carousel plugins](https://www.embla-carousel.com/plugins/).
### Autoplay
This plugin is used to extend Embla Carousel with **autoplay** functionality.
::warning
Install the `embla-carousel-autoplay` package:
::code-group
```bash [pnpm]
pnpm add embla-carousel-autoplay
```
```bash [yarn]
yarn add embla-carousel-autoplay
```
```bash [npm]
npm install embla-carousel-autoplay
```
```bash [bun]
bun add embla-carousel-autoplay
```
::
::
Use the `autoplay` prop as a boolean or an object to configure the [Autoplay plugin](https://www.embla-carousel.com/plugins/autoplay/).
::component-example
---
name: 'carousel-autoplay-example'
class: 'p-8 px-16 pb-12'
---
::
::note
In this example, we're using the `loop` prop for an infinite carousel.
::
### Auto Scroll
This plugin is used to extend Embla Carousel with **auto scroll** functionality.
::warning
Install the `embla-carousel-auto-scroll` package:
::code-group
```bash [pnpm]
pnpm add embla-carousel-auto-scroll
```
```bash [yarn]
yarn add embla-carousel-auto-scroll
```
```bash [npm]
npm install embla-carousel-auto-scroll
```
```bash [bun]
bun add embla-carousel-auto-scroll
```
::
::
Use the `auto-scroll` prop as a boolean or an object to configure the [Auto Scroll plugin](https://www.embla-carousel.com/plugins/auto-scroll/).
::component-example
---
name: 'carousel-auto-scroll-example'
class: 'p-8 px-16 pb-12'
---
::
::note
In this example, we're using the `loop` prop for an infinite carousel.
::
### Auto Height
This plugin is used to extend Embla Carousel with **auto height** functionality. It changes the height of the carousel container to fit the height of the highest slide in view.
::warning
Install the `embla-carousel-auto-height` package:
::code-group
```bash [pnpm]
pnpm add embla-carousel-auto-height
```
```bash [yarn]
yarn add embla-carousel-auto-height
```
```bash [npm]
npm install embla-carousel-auto-height
```
```bash [bun]
bun add embla-carousel-auto-height
```
::
::
Use the `auto-height` prop as a boolean or an object to configure the [Auto Height plugin](https://www.embla-carousel.com/plugins/auto-height/).
::component-example
---
name: 'carousel-auto-height-example'
class: 'p-8 pt-16'
---
::
::note
In this example, we add the `transition-[height]` class on the container to animate the height change.
::
### Class Names
Class Names is a **class name toggle** utility plugin for Embla Carousel that enables you to automate the toggling of class names on your carousel.
::warning
Install the `embla-carousel-class-names` package:
::code-group
```bash [pnpm]
pnpm add embla-carousel-class-names
```
```bash [yarn]
yarn add embla-carousel-class-names
```
```bash [npm]
npm install embla-carousel-class-names
```
```bash [bun]
bun add embla-carousel-class-names
```
::
::
Use the `class-names` prop as a boolean or an object to configure the [Class Names plugin](https://www.embla-carousel.com/plugins/class-names/).
::component-example
---
name: 'carousel-class-names-example'
class: 'p-8'
---
::
::note
In this example, we add the `transition-opacity [&:not(.is-snapped)]:opacity-10` classes on the `item` to animate the opacity change.
::
### Fade
This plugin is used to replace the Embla Carousel scroll functionality with **fade transitions**.
::warning
Install the `embla-carousel-fade` package:
::code-group
```bash [pnpm]
pnpm add embla-carousel-fade
```
```bash [yarn]
yarn add embla-carousel-fade
```
```bash [npm]
npm install embla-carousel-fade
```
```bash [bun]
bun add embla-carousel-fade
```
::
::
Use the `fade` prop as a boolean or an object to configure the [Fade plugin](https://www.embla-carousel.com/plugins/fade/).
::component-example
---
name: 'carousel-fade-example'
class: 'p-8 pb-12'
---
::
### Wheel Gestures
This plugin is used to extend Embla Carousel with the ability to **use the mouse/trackpad wheel** to navigate the carousel.
::warning
Install the `embla-carousel-wheel-gestures` package:
::code-group
```bash [pnpm]
pnpm add embla-carousel-wheel-gestures
```
```bash [yarn]
yarn add embla-carousel-wheel-gestures
```
```bash [npm]
npm install embla-carousel-wheel-gestures
```
```bash [bun]
bun add embla-carousel-wheel-gestures
```
::
::
Use the `wheel-gestures` prop as a boolean or an object to configure the [Wheel Gestures plugin](https://www.embla-carousel.com/plugins/wheel-gestures/).
::note
Use your mouse wheel to scroll the carousel.
::
::component-example
---
name: 'carousel-wheel-gestures-example'
class: 'p-8 px-16'
---
::
## API
### Props
:component-props
::component-props
---
ignore:
- as
- to
- target
- active
- activeClass
- inactiveClass
- exactActiveClass
- ariaCurrentValue
- href
- rel
- noRel
- prefetch
- prefetchOn
- noPrefetch
- prefetchedClass
- replace
- exact
- exactQuery
- exactHash
- external
- onClick
---
::
### Slots
:component-slots
### Emits
### Expose
:component-emits
When accessing the component via a template ref, you can use the following:
| Name | Type |
| ---- | ---- |
| `emblaRef`{lang="ts-type"} | `Ref<HTMLElement \| null>`{lang="ts-type"} |
| `emblaApi`{lang="ts-type"} | [`Ref<EmblaCarouselType \| null>`{lang="ts-type"}](https://www.embla-carousel.com/api/methods/#typescript) |
## Theme
:component-theme -->
:component-theme

View File

@@ -561,6 +561,7 @@ ignore:
- exactQuery
- exactHash
- external
- onClick
---
::

View File

@@ -292,6 +292,7 @@ ignore:
- exactQuery
- exactHash
- external
- onClick
---
::

View File

@@ -361,6 +361,7 @@ ignore:
- exactQuery
- exactHash
- external
- onClick
---
::

View File

@@ -381,6 +381,7 @@ ignore:
- exactQuery
- exactHash
- external
- onClick
---
::

View File

@@ -369,6 +369,7 @@ ignore:
- exactQuery
- exactHash
- external
- onClick
---
::

View File

@@ -239,6 +239,7 @@ ignore:
- exactQuery
- exactHash
- external
- onClick
---
::