Documentation
Carousel

Carousel

Powerful, lightweight and fully customizable carousel component using Embla Carousel and Tailwind.

💡

This component is not imported from @inspectra/ui. They are just a series of examples of how to build a component. You are free to develop it according to your design requirements and you can use these examples to be able to do it in a fast way

⚠️

Read the Embla Carousel (opens in a new tab) documentation to learn more about the options and how to use it

Building a carousel

Install Embla Carousel

pnpm install embla-carousel-react 

Create a component

Embla allows certain options to configure the behavior of the carousel as well as the addition of plugins such as AutoPlay

In this example a basic configuration is used

import React from "react"
import useEmblaCarousel, { EmblaOptionsType } from "embla-carousel-react"
 
export const images: string[] = [
  "/carousel/slide-1",
  "/carousel/slide-2",
  "/carousel/slide-3",
  "/carousel/slide-4",
]
 
const imageByIndex = (index: number): string => images[index % images.length]
 
type PropType = {
  slides: number[]
  options?: EmblaOptionsType
}
 
const CarouselWithTailwind = (props: PropType) => {
  const { slides, options } = props
  const [emblaRef] = useEmblaCarousel(options)
 
  return (
    <div id="carousel" className="relative">
      <div id="carousel-viewport" className="overflow-hidden" ref={emblaRef}>
        <div
          id="carousel-container"
          className="ml-[calc(1rem * -1)] flex h-auto"
        >
          {slides.map((index) => (
            <div
              id="carousel-slide"
              className="relative min-w-0 flex-[0_0_100%]"
              key={index}
            >
              <Badge
                id="carousel-slide-number"
                className="bg-dark-overlay-a7 absolute bottom-4 left-4"
              >
                {index + 1}
              </Badge>
              <img
                id="carousel-slide-img"
                className="block size-full rounded-md object-cover"
                src={imageByIndex(index)}
                alt="Your alt text"
              />
            </div>
          ))}
        </div>
      </div>
    </div>
  )
}

Use the component

Examples of interest

The following examples show different use cases that can be used for common development scenarios.

If one of these cases is compatible with the requirements, copy and paste the sample code and modify it according to your needs.

⚠️

In case you need any additional use cases, don't forget to consult the Embla examples (opens in a new tab)

Y-axis

Add axis: "y" to Embla's options to make the carousel scroll vertically instead of horizontally.

Arrows and dots

You can have a more specific control of the carousel by accessing the EmblaCarousel API through the useEmblaCarousel hook.

In this case, we can access in a very simple way to the previous and next element of the current visible element of the carousel, as well as to detect when it is or not possible to go forward or backward with the buttons of this example.

...
  const { slides, options } = props
  const [emblaRef, emblaApi] = useEmblaCarousel(options)
  const [prevBtnDisabled, setPrevBtnDisabled] = React.useState(true)
  const [nextBtnDisabled, setNextBtnDisabled] = React.useState(true)
  const [selectedIndex, setSelectedIndex] = React.useState(0)
  const [scrollSnaps, setScrollSnaps] = React.useState<number[]>([])
 
  const scrollPrev = React.useCallback(
    () => emblaApi && emblaApi.scrollPrev(),
    [emblaApi]
  )
  const scrollNext = React.useCallback(
    () => emblaApi && emblaApi.scrollNext(),
    [emblaApi]
  )
  const scrollTo = React.useCallback(
    (index: number) => emblaApi && emblaApi.scrollTo(index),
    [emblaApi]
  )
 
  const onInit = React.useCallback((emblaApi: EmblaCarouselType) => {
    setScrollSnaps(emblaApi.scrollSnapList())
  }, [])
 
  const onSelect = React.useCallback((emblaApi: EmblaCarouselType) => {
    setSelectedIndex(emblaApi.selectedScrollSnap())
    setPrevBtnDisabled(!emblaApi.canScrollPrev())
    setNextBtnDisabled(!emblaApi.canScrollNext())
  }, [])
 
  React.useEffect(() => {
    if (!emblaApi) return
 
    onInit(emblaApi)
    onSelect(emblaApi)
    emblaApi.on('reInit', onInit)
    emblaApi.on('reInit', onSelect)
    emblaApi.on('select', onSelect)
  }, [emblaApi, onInit, onSelect])
 
  return (
    ...
  )

Thumbnails