Recommended
Individual License - Lifetime Access
$199
one-time paymentBeautifully crafted React + Tailwind CSS + Framer Motion components and templates for your next web project.
What's included:
- Over 50+ sections — Everything you need to build beautiful landing pages
- 5+ templates — Templates built with React, Next.js, and TailwindCSS
- Commercial Use — Use the templates for commercial projects. Re-selling of code is NOT allowed.
- Perpetual license — You own the templates, forever
- Lifetime access — Get access to everything available today, plus everything added in the future
- Lifetime updates — Get access to all future updates for the original purchase price
Recommended
Individual License - Lifetime Access
$199
one-time paymentBeautifully crafted React + Tailwind CSS + Framer Motion components and templates for your next web project.
What's included:
- Over 50+ sections — Everything you need to build beautiful landing pages
- 5+ templates — Templates built with React, Next.js, and TailwindCSS
- Commercial Use — Use the templates for commercial projects. Re-selling of code is NOT allowed.
- Perpetual license — You own the templates, forever
- Lifetime access — Get access to everything available today, plus everything added in the future
- Lifetime updates — Get access to all future updates for the original purchase price
Installation
First, you need to first install the embla-carousel
package to get started.
npm install embla-carousel-react embla-carousel-autoplay --save
Carousel Button
Then copy paste the carousel button and indicator code into your project.
"use client"
import React, {
ComponentPropsWithRef,
useCallback,
useEffect,
useState,
} from "react"
import { EmblaCarouselType } from "embla-carousel"
type UseCarouselButtonsType = {
prevBtnDisabled: boolean
nextBtnDisabled: boolean
onPrevButtonClick: () => void
onNextButtonClick: () => void
}
export const useCarouselButtons = (
emblaApi: EmblaCarouselType | undefined,
onButtonClick?: (emblaApi: EmblaCarouselType) => void
): UseCarouselButtonsType => {
const [prevBtnDisabled, setPrevBtnDisabled] = useState(true)
const [nextBtnDisabled, setNextBtnDisabled] = useState(true)
const updateButtonStates = useCallback((emblaApi: EmblaCarouselType) => {
setPrevBtnDisabled(!emblaApi.canScrollPrev())
setNextBtnDisabled(!emblaApi.canScrollNext())
}, [])
const onPrevButtonClick = useCallback(() => {
if (!emblaApi) return
emblaApi.scrollPrev()
updateButtonStates(emblaApi)
}, [emblaApi, updateButtonStates])
const onNextButtonClick = useCallback(() => {
if (!emblaApi) return
emblaApi.scrollNext()
updateButtonStates(emblaApi)
}, [emblaApi, updateButtonStates])
useEffect(() => {
if (!emblaApi) return
updateButtonStates(emblaApi)
emblaApi
.on("select", () => updateButtonStates(emblaApi))
.on("reInit", () => updateButtonStates(emblaApi))
.on("init", () => updateButtonStates(emblaApi))
return () => {
if (emblaApi) {
emblaApi
.off("select", () => updateButtonStates(emblaApi))
.off("reInit", () => updateButtonStates(emblaApi))
.off("init", () => updateButtonStates(emblaApi))
}
}
}, [emblaApi, updateButtonStates])
return {
prevBtnDisabled,
nextBtnDisabled,
onPrevButtonClick,
onNextButtonClick,
}
}
type PropType = ComponentPropsWithRef<"button">
export const PrevButton: React.FC<PropType> = (props) => {
const { children, ...restProps } = props
return (
<button type="button" {...restProps}>
<svg className="h-[30%] w-[30%]" viewBox="0 0 532 532">
<path
fill="currentColor"
d="M355.66 11.354c13.793-13.805 36.208-13.805 50.001 0 13.785 13.804 13.785 36.238 0 50.034L201.22 266l204.442 204.61c13.785 13.805 13.785 36.239 0 50.044-13.793 13.796-36.208 13.796-50.002 0a5994246.277 5994246.277 0 0 0-229.332-229.454 35.065 35.065 0 0 1-10.326-25.126c0-9.2 3.393-18.26 10.326-25.2C172.192 194.973 332.731 34.31 355.66 11.354Z"
/>
</svg>
{children}
</button>
)
}
export const NextButton: React.FC<PropType> = (props) => {
const { children, ...restProps } = props
return (
<button type="button" {...restProps}>
<svg className="h-[30%] w-[30%]" viewBox="0 0 532 532">
<path
fill="currentColor"
d="M176.34 520.646c-13.793 13.805-36.208 13.805-50.001 0-13.785-13.804-13.785-36.238 0-50.034L330.78 266 126.34 61.391c-13.785-13.805-13.785-36.239 0-50.044 13.793-13.796 36.208-13.796 50.002 0 22.928 22.947 206.395 206.507 229.332 229.454a35.065 35.065 0 0 1 10.326 25.126c0 9.2-3.393 18.26-10.326 25.2-45.865 45.901-206.404 206.564-229.332 229.52Z"
/>
</svg>
{children}
</button>
)
}
Carousel Indicator
"use client"
import React, {
ComponentPropsWithRef,
useCallback,
useEffect,
useState,
} from "react"
import { EmblaCarouselType } from "embla-carousel"
type UseCarouselIndicatorType = {
selectedIndex: number
scrollSnaps: number[]
onDotButtonClick: (index: number) => void
}
export const useCarouselIndicator = (
emblaApi: EmblaCarouselType | undefined
): UseCarouselIndicatorType => {
const [selectedIndex, setSelectedIndex] = useState(0)
const [scrollSnaps, setScrollSnaps] = useState<number[]>([])
const onDotButtonClick = useCallback(
(index: number) => {
if (!emblaApi) return
emblaApi.scrollTo(index)
},
[emblaApi]
)
const onInit = useCallback((emblaApi: EmblaCarouselType) => {
setScrollSnaps(emblaApi.scrollSnapList())
}, [])
const onSelect = useCallback((emblaApi: EmblaCarouselType) => {
setSelectedIndex(emblaApi.selectedScrollSnap())
}, [])
useEffect(() => {
if (!emblaApi) return
onInit(emblaApi)
onSelect(emblaApi)
emblaApi.on("reInit", onInit).on("reInit", onSelect).on("select", onSelect)
return () => {
emblaApi
.off("reInit", onInit)
.off("reInit", onSelect)
.off("select", onSelect)
}
}, [emblaApi, onInit, onSelect])
return {
selectedIndex,
scrollSnaps,
onDotButtonClick,
}
}
type CarouselIndicatorProps = ComponentPropsWithRef<"button">
export const CarouselIndicator: React.FC<CarouselIndicatorProps> = (props) => {
const { children, ...restProps } = props
return (
<button type="button" {...restProps}>
{children}
</button>
)
}
Copy the carousel into your project
Props
Prop | Type | Description | Default |
---|---|---|---|
className | string | The class name to be applied to the carousel | |
slides | React.ReactNode[] | The array of slides to display in the carousel | |
options | EmblaOptionsType | Configuration options for the carousel | |
maxRotateX | number | Maximum rotation on the X-axis | 45 |
maxRotateY | number | Maximum rotation on the Y-axis | 15 |
maxScale | number | Maximum scale factor | 0.9 |
tweenFactorBase | number | Base factor for tweening effects | 0.7 |
autoplay | boolean | Enable autoplay functionality | true |
autoplayDelay | number | Delay between autoplay transitions | 2000 |
showIndicators | boolean | Show indicators for the slides | true |
showArrows | boolean | Show navigation arrows | true |