From 8ef4f200ac8f57444fc77b2aa279bbfd17a82ff6 Mon Sep 17 00:00:00 2001
From: Quan Khuc <71282105+quankhuc@users.noreply.github.com>
Date: Fri, 3 May 2024 11:16:26 -0500
Subject: [PATCH] feat(components): add carousel dot buttons
---
.../src/content/docs/components/carousel.md | 53 +++++++++----------
.../ui/carousel/CarouselDotButtons.vue | 18 +++++++
.../default/ui/carousel/useCarousel.ts | 9 +++-
.../ui/carousel/CarouselDotButtons.vue | 18 +++++++
.../new-york/ui/carousel/useCarousel.ts | 9 +++-
5 files changed, 76 insertions(+), 31 deletions(-)
create mode 100644 apps/www/src/lib/registry/default/ui/carousel/CarouselDotButtons.vue
create mode 100644 apps/www/src/lib/registry/new-york/ui/carousel/CarouselDotButtons.vue
diff --git a/apps/www/src/content/docs/components/carousel.md b/apps/www/src/content/docs/components/carousel.md
index 091b9bf7..a8ac4332 100644
--- a/apps/www/src/content/docs/components/carousel.md
+++ b/apps/www/src/content/docs/components/carousel.md
@@ -1,11 +1,8 @@
---
-title: Carousel
-description: A carousel with motion and swipe built using Embla.
-source: apps/www/src/lib/registry/default/ui/carousel
-primitive: https://www.embla-carousel.com/api
----
-
+## title: Carousel description: A carousel with motion and swipe built using Embla. source: apps/www/src/lib/registry/default/ui/carousel primitive:
+
+<ComponentPreview name="CarouselDemo" />
## About
@@ -32,6 +29,7 @@ import {
+
...
...
@@ -49,11 +47,11 @@ import {
To set the size of the items, you can use the `basis` utility class on the ``.
-
+<ComponentPreview name="CarouselSize" />
Example
-```vue:line-numbers title="Example" {4-6}
+```vue:line-numbers
// 33% of the carousel width.
@@ -66,7 +64,7 @@ Example
Responsive
-```vue:line-numbers title="Responsive" {4-6}
+```vue:line-numbers
// 50% on small screens and 33% on larger screens.
@@ -81,22 +79,17 @@ Responsive
To set the spacing between the items, we use a `pl-[VALUE]` utility on the `` and a negative `-ml-[VALUE]` on the ``.
-
+<Callout class="mt-6">
-**Why:** I tried to use the `gap` property or a `grid` layout on the `
-CarouselContent` but it required a lot of math and mental effort to get the
-spacing right. I found `pl-[VALUE]` and `-ml-[VALUE]` utilities much easier to
-use.
-
-You can always adjust this in your own project if you need to.
+**Why:** I tried to use the `gap` property or a `grid` layout on the `CarouselContent` but it required a lot of math and mental effort to get the spacing right. I found `pl-[VALUE]` and `-ml-[VALUE]` utilities much easier to use. <br/><br/> You can always adjust this in your own project if you need to.
-
+</Callout>
-
+<ComponentPreview name="CarouselSpacing" />
Example
-```vue:line-numbers /-ml-4/ /pl-4/
+```vue:line-numbers
@@ -116,7 +109,7 @@ Example
Responsive
-```vue:line-numbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
+```vue:line-numbers
@@ -138,7 +131,7 @@ Responsive
Use the `orientation` prop to set the orientation of the carousel.
-
+<ComponentPreview name="CarouselOrientation" />
```vue
@@ -148,13 +141,15 @@ Use the `orientation` prop to set the orientation of the carousel.
### Thumbnails
-
+<ComponentPreview name="CarouselThumbnails" />
+
+###
## Options
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information.
-```vue:line-numbers {3-6}
+```vue:line-numbers
+<ComponentPreview name="CarouselApi" />
### Method 2
You can access it through setting a template ref on the `` component.
-```vue:line-numbers {2,5,9}
+```vue:line-numbers
@@ -275,6 +270,6 @@ import Autoplay from 'embla-carousel-autoplay'
```
-
+<ComponentPreview name="CarouselPlugin" />
See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on using plugins.
diff --git a/apps/www/src/lib/registry/default/ui/carousel/CarouselDotButtons.vue b/apps/www/src/lib/registry/default/ui/carousel/CarouselDotButtons.vue
new file mode 100644
index 00000000..08032bcd
--- /dev/null
+++ b/apps/www/src/lib/registry/default/ui/carousel/CarouselDotButtons.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/apps/www/src/lib/registry/default/ui/carousel/useCarousel.ts b/apps/www/src/lib/registry/default/ui/carousel/useCarousel.ts
index 16be25c8..fff7bf5e 100644
--- a/apps/www/src/lib/registry/default/ui/carousel/useCarousel.ts
+++ b/apps/www/src/lib/registry/default/ui/carousel/useCarousel.ts
@@ -23,13 +23,20 @@ const [useProvideCarousel, useInjectCarousel] = createInjectionState(
function scrollNext() {
emblaApi.value?.scrollNext()
}
+ function scrollTo(index: number) {
+ emblaApi.value?.scrollTo(index)
+ }
const canScrollNext = ref(true)
const canScrollPrev = ref(true)
+ const selectedIndex = ref(0)
+ const scrollSnaps = ref([])
function onSelect(api: CarouselApi) {
canScrollNext.value = api.canScrollNext()
canScrollPrev.value = api.canScrollPrev()
+ selectedIndex.value = api.selectedScrollSnap()
+ scrollSnaps.value = api.scrollSnapList()
}
onMounted(() => {
@@ -43,7 +50,7 @@ const [useProvideCarousel, useInjectCarousel] = createInjectionState(
emits('init-api', emblaApi.value)
})
- return { carouselRef: emblaNode, carouselApi: emblaApi, canScrollPrev, canScrollNext, scrollPrev, scrollNext, orientation }
+ return { carouselRef: emblaNode, carouselApi: emblaApi, canScrollPrev, canScrollNext, scrollPrev, scrollNext, scrollTo, scrollSnaps, selectedIndex, orientation }
},
)
diff --git a/apps/www/src/lib/registry/new-york/ui/carousel/CarouselDotButtons.vue b/apps/www/src/lib/registry/new-york/ui/carousel/CarouselDotButtons.vue
new file mode 100644
index 00000000..d917b325
--- /dev/null
+++ b/apps/www/src/lib/registry/new-york/ui/carousel/CarouselDotButtons.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/apps/www/src/lib/registry/new-york/ui/carousel/useCarousel.ts b/apps/www/src/lib/registry/new-york/ui/carousel/useCarousel.ts
index 16be25c8..fff7bf5e 100644
--- a/apps/www/src/lib/registry/new-york/ui/carousel/useCarousel.ts
+++ b/apps/www/src/lib/registry/new-york/ui/carousel/useCarousel.ts
@@ -23,13 +23,20 @@ const [useProvideCarousel, useInjectCarousel] = createInjectionState(
function scrollNext() {
emblaApi.value?.scrollNext()
}
+ function scrollTo(index: number) {
+ emblaApi.value?.scrollTo(index)
+ }
const canScrollNext = ref(true)
const canScrollPrev = ref(true)
+ const selectedIndex = ref(0)
+ const scrollSnaps = ref([])
function onSelect(api: CarouselApi) {
canScrollNext.value = api.canScrollNext()
canScrollPrev.value = api.canScrollPrev()
+ selectedIndex.value = api.selectedScrollSnap()
+ scrollSnaps.value = api.scrollSnapList()
}
onMounted(() => {
@@ -43,7 +50,7 @@ const [useProvideCarousel, useInjectCarousel] = createInjectionState(
emits('init-api', emblaApi.value)
})
- return { carouselRef: emblaNode, carouselApi: emblaApi, canScrollPrev, canScrollNext, scrollPrev, scrollNext, orientation }
+ return { carouselRef: emblaNode, carouselApi: emblaApi, canScrollPrev, canScrollNext, scrollPrev, scrollNext, scrollTo, scrollSnaps, selectedIndex, orientation }
},
)